diff --git a/stepmania/Utils/Font generation/Output/placeholder.txt b/stepmania/Utils/Font generation/Output/placeholder.txt new file mode 100644 index 0000000000..2c0c083733 --- /dev/null +++ b/stepmania/Utils/Font generation/Output/placeholder.txt @@ -0,0 +1 @@ +Generated font pages go here. (placeholder to make CVS create dir) diff --git a/stepmania/Utils/Font generation/Templates/kanji 1 template.psd b/stepmania/Utils/Font generation/Templates/kanji 1 template.psd new file mode 100644 index 0000000000..5b16615a02 Binary files /dev/null and b/stepmania/Utils/Font generation/Templates/kanji 1 template.psd differ diff --git a/stepmania/Utils/Font generation/Templates/kanji 2 template.psd b/stepmania/Utils/Font generation/Templates/kanji 2 template.psd new file mode 100644 index 0000000000..7bfb576eb8 Binary files /dev/null and b/stepmania/Utils/Font generation/Templates/kanji 2 template.psd differ diff --git a/stepmania/Utils/Font generation/Templates/kanji 3 template.psd b/stepmania/Utils/Font generation/Templates/kanji 3 template.psd new file mode 100644 index 0000000000..de776e9930 Binary files /dev/null and b/stepmania/Utils/Font generation/Templates/kanji 3 template.psd differ diff --git a/stepmania/Utils/Font generation/Templates/main template.psd b/stepmania/Utils/Font generation/Templates/main template.psd new file mode 100644 index 0000000000..717f568462 Binary files /dev/null and b/stepmania/Utils/Font generation/Templates/main template.psd differ diff --git a/stepmania/Utils/Font generation/Text.js b/stepmania/Utils/Font generation/Text.js new file mode 100644 index 0000000000..95980f5ff3 --- /dev/null +++ b/stepmania/Utils/Font generation/Text.js @@ -0,0 +1,351 @@ +/* This file was written by Glenn Maynard, and is in the public domain. + * + * This is a Photoshop javascript to generate Kanji fonts. + * + * You'll need the plugin: + * + * http://www.adobe.com/support/downloads/detail.jsp?ftpID=1536 + * + * Load this script from File->Automation->Scripts, browse. Expect it to take + * a minute or two. + * + * Minimally, you'll need to edit the directories below. + * + * Each font page in FontPages is generated for each font in Fonts. + * + * I can't figure out a way to force a font to fixed-width, so this currently + * only works with fixed-width fonts. I'm using this primarily for Japanese + * fonts, so that's OK. If we could output Unicode, we could get around this, + * by outputting each glyph in a separate layer and aligning them individually, + * though that'd take a very long time. + */ + +/* Okay, this is a stupid way to pass by reference, but I don't speak JavaScript ... */ +function Integer(i) { this.val = i; } + +var TemplateDir = "c:/temp/stepmania/utils/Font generation/Templates/"; +var OutputDir = "c:/temp/stepmania/utils/Font generation/Output/"; + +var Fonts = new Array( + /* name font frame sz font sz AA border bold */ + new FontDef("_japanese 16px", "MS-Gothic", 32, 20, AntiAlias.STRONG, 2, true), + new FontDef("_japanese 24px", "MS-Gothic", 32, 28, AntiAlias.SMOOTH, 2, true) + ); + + +/* We can't send Unicode into the font ourself for some reason. So, we have to + * store prototypes for each font page. These should just be PSD files that contain + * a single text layer with the characters we want. The orientation, font, etc. + * don't matter; they'll be overridden. */ +var FontPages = Array("main", "kanji 1", "kanji 2","kanji 3"); + +var sel, doc; + +var strtRulerUnits = preferences.rulerUnits; +var strtTypeUnits = preferences.typeUnits; +preferences.rulerUnits = Units.PIXELS; +preferences.typeUnits = TypeUnits.PIXELS; +displayDialogs = DialogModes.NO; + +go(); + +preferences.rulerUnits = strtRulerUnits; +preferences.typeUnits = strtTypeUnits; + +function FontDef(Name, /* filename prefix */ + Font, /* actual font name */ + FrameSize, /* frame size in pixels */ + FontSize, /* font character size in pixels (horiz) */ + AAMethod, /* antialiasing */ + Border, /* pixels or 0 for off */ + Bold /* boolean */ + ) +{ + this.Name = Name; + this.Font = Font; + + this.FrameSize = FrameSize; + /* This is the width of each character, as output by the font renderer. + * Changing this changes the size of the character. */ + + this.HorizSize = FontSize; + /* This is the actual vertical size of characters, as output by the font renderer. + * For MS Gothic, it always seems to be 4/3 of the vertical size. */ + this.VertSize = FontSize* 4 / 3; + this.AAMethod = AAMethod; + this.Border = Border; + this.Bold = Bold; +} + +function go() +{ + for(var f = 0; f < Fonts.length; ++f) + { + for(var i = 0; i < FontPages.length; ++i) + { + MakeFontPage(TemplateDir + FontPages[i] + " template.psd", + OutputDir + Fonts[f].Name + " [" + FontPages[i] + "]", + Fonts[f]); + } + } +} + +function MakeFontPage(TemplatePath, OutputPath, Font) +{ + /* Open the template. */ + var file = new File(TemplatePath); + if(!file.open("r")) + { + alert("Couldn't open " + TemplatePath); + return; + } + open(file); + file = null; + + /* Change the template to a font page. */ + var frameX = new Integer; + var frameY = new Integer; + ConvertCurrentDocument(frameX, frameY, Font); + + /* Save the template to the destination file and close the template. */ + var Save = new PNGSaveOptions; + Save.interlaced = false; + OutputPath += " " + frameX.val + "x" + frameY.val; + OutputPath += ".png"; + activeDocument.saveAs(new File(OutputPath), Save, true, Extension.LOWERCASE); + activeDocument.close(SaveOptions.DONOTSAVECHANGES); +} + +function GetTextLayer(Doc) +{ + /* Find a text layer. */ + var TextLayer = null; + for(var i = 0; i < activeDocument.artLayers.length; ++i) + { + if(activeDocument.artLayers[i].kind != LayerKind.TEXT) + continue; /* irrelevant */ + + if(TextLayer != null) + { + alert("More than one text layer found. Confused."); + return null; + } + + TextLayer = activeDocument.artLayers[i]; + } + + if(TextLayer == null) + { + alert("No text layer found. Confused."); + return null; + } + + return TextLayer; +} + +/* We have an open document with a single text layer. Convert it to a font + * page. The result will be a single RGB layer. */ +function ConvertCurrentDocument( frameX, frameY, Font ) +{ + // Create a new art layer and convert it to a text layer. + // Set its contents, size and color. + if (documents.length == 0) + { + alert ("You must have at least one open document to run this script."); + return; + } + + doc = activeDocument; + sel = doc.selection; + + /* Find a text layer. */ + var TextLayer = GetTextLayer(doc); + if(TextLayer == null) return; + + /* Figure out the number of frames in each dimension, based on the line count + * and max characters/line. */ + GetFrameCount(TextLayer.textItem.contents, frameX, frameY); + + /* Based on the frame count and frame size, figure out the dimensions of + * the whole page. */ + var PageWidth = frameX.val * Font.FrameSize; + var PageHeight = frameY.val * Font.FrameSize; + + /* Resize the image down to the size required to hold the images. This prevents + * errors later when we move columns around if the image is too big. */ + doc.resizeCanvas(PageWidth, PageHeight, AnchorPosition.TOPLEFT); + + { + /* Using HorizSize as the vertical origin seems to align the text so that + * it's centered in the top VertSize pixels. Adjust from there to being centered + * in the frame. */ + var Dist = Font.FrameSize/2-Font.VertSize/2; + TextLayer.textItem.position = Array(0, Font.HorizSize+Dist); + } + + TextLayer.textItem.font = Font.Font; + TextLayer.textItem.antiAliasMethod = Font.AAMethod; + var textColor = new SolidColor; + textColor.rgb.red = 255; + textColor.rgb.green = 255; + textColor.rgb.blue = 255; + + TextLayer.textItem.color = textColor; + + TextLayer.textItem.useAutoLeading = 0; + TextLayer.textItem.spaceBefore = Font.FrameSize; + TextLayer.textItem.spaceAfter = 0; + + TextLayer.textItem.size = Font.HorizSize; + + TextLayer.textItem.fauxBold = Font.Bold; + TextLayer.textItem.fauxItalic = false; + + TextLayer.rasterize(RasterizeType.ENTIRELAYER); + + var CurrentSpacing = Font.HorizSize; + /* Faux bold adds half a pixel to the widht of each character. */ + if(Font.Bold) + CurrentSpacing += 0.5; + + /* We currently have a horizontal spacing of CurrentSpacing; adjust it to + * have a vertical spacing of FrameSize. */ + Adjust(Font.FrameSize, CurrentSpacing, frameX.val); + + if(Font.Border != 0) + TextLayer = MakeBorder(TextLayer, doc.artLayers, Font.Border); + + { + /* Resize the texture to have the largest possible frame count without going + * over a power of two. This way, when the font page grows, the frame count + * (8x8) stays constant, so we don't have to keep renaming files in CVS. */ + var MaxX = power_of_two(PageWidth); + var MaxY = power_of_two(PageHeight); + while(PageWidth + Font.FrameSize <= MaxX) + PageWidth += Font.FrameSize; + while(PageHeight + Font.FrameSize <= MaxY) + PageHeight += Font.FrameSize; + + /* Actually, let's force the texture to be square, too, which reduces filename + * changes even more. This eats a little texture memory. It also means that + * if the texture is reduced at runtime, it'll be reduced equally in both + * dimensions, which will probably look less weird. */ + if(PageHeight < PageWidth) PageHeight = PageWidth; + else PageWidth = PageHeight; + + frameX.val = PageWidth / Font.FrameSize; + frameY.val = PageHeight / Font.FrameSize; + } + doc.resizeCanvas(PageWidth, PageHeight, AnchorPosition.TOPLEFT); +} + +function GetFrameCount(str, x, y) +{ + /* Strip blank lines off the end. */ + for(var c = str.length-1; c >= 0; --c) + { + if(c != '\r' && c != ' ') + break; + str = str.substr(0, str.length-1); + } + + var NumLines = 0, MaxLength = 0, CurLength = 0; + + for(var c = 0; c < str.length; ++c) + { + if(str[c] == '\r') + { + CurLength = 0; + NumLines++; + } + else + { + CurLength++; + if(CurLength > MaxLength) + MaxLength = CurLength; + } + } + if(CurLength) + NumLines++; + + x.val = MaxLength; + y.val = NumLines; +} + +function power_of_two(n) +{ + var value = 1; + + while (value < n) + value *= 2; + + return value; +} + +/* The current document is in columns of width NewWidth. Space it out so the columns + * are of width OldWidth. */ +function Adjust(NewWidth, OldWidth, Columns) +{ + // col = 7; + for(var col = Columns-1; col >= 0; --col) + { + var selBounds = Array( + Array(col*OldWidth,0), + Array((col+1)*OldWidth, 0), + Array((col+1)*OldWidth, activeDocument.height), + Array(col*OldWidth, activeDocument.height)); + sel.select(selBounds); + + var OldXCenter = (col + .5) * OldWidth; + var NewXCenter = (col + .5) * NewWidth; + var Distance = NewXCenter-OldXCenter; + sel.translate(Distance); + } + sel.deselect(); +} + +function SelectTransparencyFromCurrentLayer() +{ + // Voodoo from the action recorder, since I couldn't find a way to + // do this normally. + var id15 = charIDToTypeID( "setd" ); + var desc3 = new ActionDescriptor(); + var id16 = charIDToTypeID( "null" ); + var ref1 = new ActionReference(); + var id17 = charIDToTypeID( "Chnl" ); + var id18 = charIDToTypeID( "fsel" ); + ref1.putProperty( id17, id18 ); + desc3.putReference( id16, ref1 ); + var id19 = charIDToTypeID( "T " ); + var ref2 = new ActionReference(); + var id20 = charIDToTypeID( "Chnl" ); + var id21 = charIDToTypeID( "Chnl" ); + var id22 = charIDToTypeID( "Trsp" ); + ref2.putEnumerated( id20, id21, id22 ); + desc3.putReference( id19, ref2 ); + executeAction( id15, desc3, DialogModes.NO ); +} + +/* Add a border to the current layer. */ +function MakeBorder(Layer, Layers, Width) +{ + SelectTransparencyFromCurrentLayer(); + sel.expand(Width); + + var BorderLayer = Layers.add(); + BorderLayer.moveAfter(Layer); + + var borderColor = new SolidColor; + borderColor.rgb.red = 0; + borderColor.rgb.green = 0; + borderColor.rgb.blue = 0; + + sel.fill(borderColor); + sel.deselect(); + + Layer.merge(); + + return BorderLayer; +} + +