@@ -90,6 +90,8 @@ local function OutputDescriptor()
9090 filenameImage = "",
9191 filenameDescriptor = "",
9292
93+ descriptorFormat = "text", -- "text"|"xml"
94+
9395 glyphColor = {1,1,1,1},
9496
9597 glyphPaddingU = 0,
@@ -555,6 +557,9 @@ function love.run()
555557 local path = normalizePath(v ~= "" and v or fileError(rbmfFile, "Path cannot be empty."))
556558 currentOutDescr.filenameDescriptor = processPathTemplate(rbmfFile, path)
557559
560+ elseif k == "descriptorFormat" then
561+ currentOutDescr.descriptorFormat = (v == "text" or v == "xml") and v or fileError(rbmfFile, "Invalid descriptor format '%s'. (Valid values: text, xml)", v)
562+
558563 elseif k == "glyphColor" then
559564 local c = currentOutDescr.glyphColor
560565 c[1], c[2], c[3], c[4] = fileAssert(rbmfFile, parseColor(v))
@@ -1172,6 +1177,16 @@ function love.run()
11721177 --
11731178 -- Write output images and descriptors
11741179 --
1180+ local function encodeXmlEntities(v)
1181+ return (v:gsub("[<>&\"']", {
1182+ ["<"] = "<",
1183+ [">"] = ">",
1184+ ["&"] = "&",
1185+ ['"'] = """,
1186+ ["'"] = "'",
1187+ }))
1188+ end
1189+
11751190 for outIndex, outDescr in ipairs(rbmfFile.outputDescriptors) do
11761191 -- @Feature: Automatic kerning calculations?
11771192
@@ -1273,44 +1288,98 @@ function love.run()
12731288 -- Start writing descriptor.
12741289 local out_descriptorBuffer = {}
12751290
1276- table.insert(out_descriptorBuffer, F(
1277- -- @Polish: Output correct value for 'smooth' and 'aa'. (Is this always possible, or ever useful?)
1278- -- @Polish: Maybe have a way of specifying 'bold' and 'italic' (though it's probably useless information).
1279- -- @Polish: We can do more here, but it's all probably useless!
1280- 'info face="" size=%d bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=0 aa=0 padding=%d,%d,%d,%d spacing=%d,%d outline=%d',
1281- in_lineHeight, -- size
1282- outDescr.glyphPaddingU, outDescr.glyphPaddingR, outDescr.glyphPaddingD, outDescr.glyphPaddingL, -- padding
1283- outDescr.glyphSpacingH, outDescr.glyphSpacingV, -- spacing
1284- outDescr.outlineWidth -- outline
1285- ))
1286- for _, k in ipairs(outDescr.customValues) do
1287- local v = outDescr.customValues[k]
1288- table.insert(out_descriptorBuffer, F(" CUSTOM_%s=", k))
1289- table.insert(out_descriptorBuffer, v:find"^%-?%d*%.?%d+$" and v or F('"%s"', v))
1291+ if outDescr.descriptorFormat == "xml" then
1292+ table.insert(out_descriptorBuffer, '<?xml version="1.0"?>\n')
1293+ table.insert(out_descriptorBuffer, "<font>\n")
1294+ end
1295+
1296+ if outDescr.descriptorFormat == "text" then
1297+ table.insert(out_descriptorBuffer, F(
1298+ -- @Polish: Output correct value for 'smooth' and 'aa'. (Is this always possible, or ever useful?)
1299+ -- @Polish: Maybe have a way of specifying 'bold' and 'italic' (though it's probably useless information).
1300+ -- @Polish: We can do more here, but it's all probably useless!
1301+ 'info face="" size=%d bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=0 aa=0 padding=%d,%d,%d,%d spacing=%d,%d outline=%d',
1302+ in_lineHeight, -- size
1303+ outDescr.glyphPaddingU, outDescr.glyphPaddingR, outDescr.glyphPaddingD, outDescr.glyphPaddingL, -- padding
1304+ outDescr.glyphSpacingH, outDescr.glyphSpacingV, -- spacing
1305+ outDescr.outlineWidth -- outline
1306+ ))
1307+ for _, k in ipairs(outDescr.customValues) do
1308+ local v = outDescr.customValues[k]
1309+ table.insert(out_descriptorBuffer, F(" CUSTOM_%s=", k)) -- Note: Characters used in 'k' should already be validated.
1310+ table.insert(out_descriptorBuffer, v:find"^%-?%d*%.?%d+$" and v or F('"%s"', v))
1311+ end
1312+ table.insert(out_descriptorBuffer, "\n")
1313+
1314+ elseif outDescr.descriptorFormat == "xml" then
1315+ table.insert(out_descriptorBuffer, F(
1316+ -- @Polish: See above!
1317+ '<info face="" size="%d" bold="0" italic="0" charset="" unicode="1" stretchH="100" smooth="0" aa="0" padding="%d,%d,%d,%d" spacing="%d,%d" outline="%d"',
1318+ in_lineHeight, -- size
1319+ outDescr.glyphPaddingU, outDescr.glyphPaddingR, outDescr.glyphPaddingD, outDescr.glyphPaddingL, -- padding
1320+ outDescr.glyphSpacingH, outDescr.glyphSpacingV, -- spacing
1321+ outDescr.outlineWidth -- outline
1322+ ))
1323+ for _, k in ipairs(outDescr.customValues) do
1324+ local v = outDescr.customValues[k]
1325+ table.insert(out_descriptorBuffer, F(' CUSTOM_%s="%s"', k, encodeXmlEntities(v))) -- Note: Characters used in 'k' should already be validated.
1326+ end
1327+ table.insert(out_descriptorBuffer, "/>\n")
1328+
1329+ else
1330+ error(outDescr.descriptorFormat)
12901331 end
1291- table.insert(out_descriptorBuffer, "\n")
12921332
12931333 local out_lineHeight = (
12941334 in_lineHeight
12951335 + (outDescr.paddingAffectsRenderSpacing and outDescr.glyphPaddingU+outDescr.glyphPaddingD or 0)
12961336 + (outDescr.outlineAffectsRenderSpacing and outDescr.outlineWidth or 0)
12971337 )
12981338
1299- table.insert(out_descriptorBuffer, F(
1300- 'common lineHeight=%d base=%d scaleW=%d scaleH=%d pages=%d packed=%d alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0\n',
1301- out_lineHeight, -- lineHeight
1302- out_lineHeight, -- base @Incomplete: Some way of specifying this. (Probably low priority.)
1303- pageWidth, pageHeight, -- scaleW, scaleH
1304- #out_imageDatas, -- pages
1305- (outDescr.pack and 1 or 0) -- packed
1306- ))
1339+ if outDescr.descriptorFormat == "text" then
1340+ table.insert(out_descriptorBuffer, F(
1341+ 'common lineHeight=%d base=%d scaleW=%d scaleH=%d pages=%d packed=%d alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0\n',
1342+ out_lineHeight, -- lineHeight
1343+ out_lineHeight, -- base @Incomplete: Some way of specifying this. (Probably low priority.)
1344+ pageWidth, pageHeight, -- scaleW, scaleH
1345+ #out_imageDatas, -- pages
1346+ (outDescr.pack and 1 or 0) -- packed
1347+ ))
1348+ elseif outDescr.descriptorFormat == "xml" then
1349+ table.insert(out_descriptorBuffer, F(
1350+ '<common lineHeight="%d" base="%d" scaleW="%d" scaleH="%d" pages="%d" packed="%d" alphaChnl="0" redChnl="0" greenChnl="0" blueChnl="0"/>\n',
1351+ out_lineHeight, -- lineHeight
1352+ out_lineHeight, -- base @Incomplete: Some way of specifying this. (Probably low priority.)
1353+ pageWidth, pageHeight, -- scaleW, scaleH
1354+ #out_imageDatas, -- pages
1355+ (outDescr.pack and 1 or 0) -- packed
1356+ ))
1357+ else
1358+ error(outDescr.descriptorFormat)
1359+ end
13071360
13081361 -- Write glyphs.
1309- for page = 1, #out_imageDatas do
1310- table.insert(out_descriptorBuffer, F('page id=%d file="%s"\n', page-1, outputImageFilenameBaseToFilename(outDescr.filenameImage, page)))
1362+ if outDescr.descriptorFormat == "text" then
1363+ for page = 1, #out_imageDatas do
1364+ table.insert(out_descriptorBuffer, F('page id=%d file="%s"\n', page-1, outputImageFilenameBaseToFilename(outDescr.filenameImage, page)))
1365+ end
1366+ elseif outDescr.descriptorFormat == "xml" then
1367+ table.insert(out_descriptorBuffer, "<pages>\n")
1368+ for page = 1, #out_imageDatas do
1369+ table.insert(out_descriptorBuffer, F('\t<page id="%d" file="%s"/>\n', page-1, encodeXmlEntities(outputImageFilenameBaseToFilename(outDescr.filenameImage, page))))
1370+ end
1371+ table.insert(out_descriptorBuffer, "</pages>\n")
1372+ else
1373+ error(outDescr.descriptorFormat)
13111374 end
13121375
1313- table.insert(out_descriptorBuffer, F('chars count=%d\n', #glyphs))
1376+ if outDescr.descriptorFormat == "text" then
1377+ table.insert(out_descriptorBuffer, F('chars count=%d\n', #glyphs))
1378+ elseif outDescr.descriptorFormat == "xml" then
1379+ table.insert(out_descriptorBuffer, F('<chars count="%d">\n', #glyphs))
1380+ else
1381+ error(outDescr.descriptorFormat)
1382+ end
13141383
13151384 -- for _, data in ipairs(out_imageDatas) do data:mapPixel(function(x,y, r,g,b,a) return 1, 0, 0, 1 end) end -- DEBUG: Show areas we don't paste glyphs in.
13161385
@@ -1417,16 +1486,35 @@ function love.run()
14171486 + (outDescr.outlineAffectsRenderSpacing and outDescr.outlineWidth or 0)
14181487 )
14191488 )
1420- table.insert(out_descriptorBuffer, F(
1421- 'char id=%d x=%d y=%d width=%d height=%d xoffset=%d yoffset=%d xadvance=%d page=%d chnl=%d\n',
1422- glyphInfo.cp, -- id
1423- glyphInfo.outX, glyphInfo.outY, -- x, y
1424- glyphInfo.outW, glyphInfo.outH, -- width, height
1425- glyphInfo.inOffsetX, glyphInfo.inOffsetY, -- xoffset, yoffset
1426- xAdvance, -- xadvance
1427- glyphInfo.outPage-1, -- page
1428- (outDescr.pack and 2^(glyphInfo.outChannel-1) or 15) -- chnl
1429- ))
1489+ if outDescr.descriptorFormat == "text" then
1490+ table.insert(out_descriptorBuffer, F(
1491+ 'char id=%d x=%d y=%d width=%d height=%d xoffset=%d yoffset=%d xadvance=%d page=%d chnl=%d\n',
1492+ glyphInfo.cp, -- id
1493+ glyphInfo.outX, glyphInfo.outY, -- x, y
1494+ glyphInfo.outW, glyphInfo.outH, -- width, height
1495+ glyphInfo.inOffsetX, glyphInfo.inOffsetY, -- xoffset, yoffset
1496+ xAdvance, -- xadvance
1497+ glyphInfo.outPage-1, -- page
1498+ (outDescr.pack and 2^(glyphInfo.outChannel-1) or 15) -- chnl
1499+ ))
1500+ elseif outDescr.descriptorFormat == "xml" then
1501+ table.insert(out_descriptorBuffer, F(
1502+ '\t<char id="%d" x="%d" y="%d" width="%d" height="%d" xoffset="%d" yoffset="%d" xadvance="%d" page="%d" chnl="%d"/>\n',
1503+ glyphInfo.cp, -- id
1504+ glyphInfo.outX, glyphInfo.outY, -- x, y
1505+ glyphInfo.outW, glyphInfo.outH, -- width, height
1506+ glyphInfo.inOffsetX, glyphInfo.inOffsetY, -- xoffset, yoffset
1507+ xAdvance, -- xadvance
1508+ glyphInfo.outPage-1, -- page
1509+ (outDescr.pack and 2^(glyphInfo.outChannel-1) or 15) -- chnl
1510+ ))
1511+ else
1512+ error(outDescr.descriptorFormat)
1513+ end
1514+ end
1515+
1516+ if outDescr.descriptorFormat == "xml" then
1517+ table.insert(out_descriptorBuffer, F('</chars>\n', #glyphs))
14301518 end
14311519
14321520 -- Add glyph outlines.
@@ -1705,7 +1793,13 @@ function love.run()
17051793 if kerningPairs[1] then
17061794 table.sort(kerningPairs)
17071795
1708- table.insert(out_descriptorBuffer, F('kernings count=%d\n', #kerningPairs))
1796+ if outDescr.descriptorFormat == "text" then
1797+ table.insert(out_descriptorBuffer, F('kernings count=%d\n', #kerningPairs))
1798+ elseif outDescr.descriptorFormat == "xml" then
1799+ table.insert(out_descriptorBuffer, F('<kernings count="%d">\n', #kerningPairs))
1800+ else
1801+ error(outDescr.descriptorFormat)
1802+ end
17091803
17101804 for _, pair in ipairs(kerningPairs) do
17111805 local first, second = pair:match(F("(%s)(%s)", utf8.charpattern, utf8.charpattern))
@@ -1714,7 +1808,17 @@ function love.run()
17141808
17151809 local offset = rbmfFile.kernings[pair]
17161810
1717- table.insert(out_descriptorBuffer, F('kerning first=%d second=%d amount=%d\n', first, second, offset))
1811+ if outDescr.descriptorFormat == "text" then
1812+ table.insert(out_descriptorBuffer, F('kerning first=%d second=%d amount=%d\n', first, second, offset))
1813+ elseif outDescr.descriptorFormat == "xml" then
1814+ table.insert(out_descriptorBuffer, F('\t<kerning first="%d" second="%d" amount="%d"/>\n', first, second, offset))
1815+ else
1816+ error(outDescr.descriptorFormat)
1817+ end
1818+ end
1819+
1820+ if outDescr.descriptorFormat == "xml" then
1821+ table.insert(out_descriptorBuffer, '</kernings>\n')
17181822 end
17191823 end
17201824
@@ -1752,6 +1856,10 @@ function love.run()
17521856 end
17531857
17541858 if outDescr.filenameDescriptor ~= "" then
1859+ if outDescr.descriptorFormat == "xml" then
1860+ table.insert(out_descriptorBuffer, '</font>\n')
1861+ end
1862+
17551863 local pathObj = Path(outDescr.filenameDescriptor, rbmfFile.outDirectory)
17561864 local dir, filename = pathObj:getDirectoryAndFilename()
17571865
0 commit comments