Open elanhickler opened 6 years ago
If you work on implementing a vector-based version of your font drawer, I'd agree to recreate all your characters in vector. You interested? This would be more for fun. I'm not sure if I will make use of it... maybe... maybemaybe.
oooh - nice! how do you do that? i mean, how do you achieve the font to look pixel-perfect? by drawing the vectors on a pixel grid? what tool do you use for that? in the long run, scalable fonts would certainly be desirable. juce actually does all that already, but the quality is very blurry - especially for bright-on-dark text (which was the reason for me to go through this tedious work of creating my own (pixel) font)
Yes, just like you tediously went through creating your own pixel font, the process is very similar to creating the vector font. You put points on the pixel grid. Affinity Designer is perfect for this because it has a curve tool to get perfect curves.
i just added my prototype pixel fonts to the repo, for reference. the main widget font is RoundedA10D0Bold.fon. i created these fonts back then with a tool called "Fony" and then hardcoded them (and yeah - the big 16 pixel font is still incomplete - some number digits are missing - or actually not missing but rather just copied-and-pasted-and-not-yet-edited from a smaller version). i think, maybe the best strategy would be to pre-render a vector-based font into pixel-fonts for all required sizes (so we don't have to fire up a full blown 2D renderer for each glyph, each time it is needed). i will check out this Affinity Designer myself, too...
learn about the corner tool.
oh - it's commercial software and there doesn't seem to be a demo available...hmm...i wonder if inkscape can do this, too...to what format do save the output then? svg?
ah - ok - thanks. ...this little text-link is quite hard to find at the bottom of a mile-high page of colorful graphics. haha.
btw. you may have noticed that in my fonts, no character goes below the baseline, such as p,q,g,etc. i did this on purpose to save vertical space which would otherwise go unused most of the time. looks a bit unusual, but that was a sort of pragmatic consideration - how to squeeze the most readable text into the smallest amount of (vertical) space. this is also the reason why i use horizontal sliders. they are most economic spatially, because i can put the text on the slider (rather than below, above or whatever)
To maintain perfect accuracy, I am trying to do it by eye and by 1D curve nodes rather than affinity's fancy coner tool with 2D shapes. This allows me to set a stroke size of 3 pixels on the 1D curve's stroke to get perfect 3 pixel width for the whole shape. So I think really any vector program would work for this.
(I have it offset .5 pixels to make it easier to trace by eye)
Try Gravit Designer, it's free. I might switch to using gravit designer for this. I can also try Inkscape, whichever is the best for making 1D curves, that's the one to use. Oh... but the 2D method is good for simple shapes like O 0 8. Hmm, yeah, I'll just have to use the method that works the best for the given glyph.
top: original others: 3 / 2 / 1 pixel stroke edit: if using 1 pixel stroke or smallest possible font size, better to use original bitmap font edit: the 2 pixel size '2' is fuzzy because I didn't realize I needed to adjust the curve for 2 pixel size. Hmm, looks like arbitrary stroke size won't work so well unless you have a system of quantizing the nodes.
x2 zoom
I only got interested in this so that you could have pixel perfect font AND when you resize the gui to be bigger, the font doesn't look ugly and pixely. Pixel-perfect vector font only has an advantage over bitmap font when it's not the smallest possible font and when not using large font (then any font looks good). It's only the middle ground that this is useful.
OH! If you could disable antialiasing conditionally (for smallest/original sizes) then vector could work in all cases... I think!
How do I use these fonts? What settings do I use? Is there a specific font size I needt o use for a given file? There should only be 2 font for the 2 sizes.
i have a baseclass BitmapFont
in jura and the actual fonts are all subclasses of that. when i need to draw text, i call drawBitmapFontText (a global function defined in GraphicsTools.cpp) which has as one of the parameters a pointer to the BitmapFont baseclass. when i call this for a widget, i pass a pointer to an object that is a static member of the respective font class. ...so basically, like a global object but to be accessed via the class - for example:
class BitmapFontRoundedA7D0 : public BitmapFont
{
static const BitmapFontRoundedA7D0 instance;
//... more stuff
};
and can be called like:
drawBitmapFontText(g, x, y, text, &BitmapFontRoundedA7D0::instance, color);
but for convenience, the RWigdet class stores the pointer &BitmapFontRoundedA7D0::instance
in the static font
member
Vector / Bitmap / Original
1x zoom (bitmap wins)
2x zoom (vector wins)
I think if we could just disable antialiasing for this example then the vector would be rendered like the bitmap and we'd have best of all worlds.
how did you render these? and what is "original"?
I'm doing all this by hand in a vector program, nothing fancy. Original is how that s*** would look rendered in the real world. It's night and day difference between pixel perfect and normal. The 2x zoom... ignore that for the original.
Going to need pixel perfect font for this. Do you have a general purpose class for placing letters? I could save each letter as a ~png~ vector file. Would also be nice to have a setting for pixel space between letters or fixed distance for monospace. Hmm, I could make my own class for this that takes vectors, renders images per font per desired size (only integer multiple sizes allowed, x1, x2, x3, etc.), then yeah, paints the text based on the string.
i have the function
/** Draws a text with a BitmapFont with the given style-settings and returns the x-coordinate where
the drawn text ends (and subsequent text can be appended, if desired). */
JUCE_API int drawBitmapFontText(Graphics &g, int x, int y, const juce::String& textToDraw,
const BitmapFont* fontToUse, const Colour& colourToUse, int kerning = -1,
Justification justification = Justification::topLeft);
in jura_GraphicsTools.h. besides othe things, it takes a pointer to a BitmapFont
object. subclasses of that class store a (sort of) image for each glyph (actually just a juce grayscale image repurposed to store alpha-values). these glyph images are pre-rendered in the class constructor by the function createGlyphBitmaps
(which a subclass can override). in my own subclasses, i just stupidly hardcode these bitmaps, but you could certainly also invoke a vector renderer there
the gui mock up looks good, btw. looking forward to see the finished product
example: This is your font spelling out LFO 2 and my vector recreation:
If you draw fonts using a series of vectors instead of bitmaps you can have nice antialiasing while maintaining pixel perfection. It's just a matter of creating the vectors for each character.
Another advantage is being able to resize. To maintain pixel perfection you of course can only use multiples of 1x, 2x, 3x zoom, etc.
If you wanted more zoom ratios like 1.5, you'd have to create a new version of the font. Here's one experiment I did for 1.0, 1.5, and 2.0 rations (2.0 is the same as 1.0)
Of course after a certain size of font, it really doesn't matter. So creating 2 to 4 small sizes for a font would be plenty.