Problem with Graphics(Image&)

I’m using my own LowLevelSoftwareRenderer now, and I’ve run into issues with some components where the text is not displayed in a normal fashion.

So far this seems to happen with TabbedButtonBar’s TabButtons. I’ve tracked down the problem to:

LowLevelGraphicsContext* createLowLevelContext() { return new LowLevelGraphicsSoftwareRenderer (Image (this)); }

In fact, to use my renderer, this function would have to call LookAndFeel::createGraphicsContext(). Is it possible to modify this? In cases it seems not to be possible because the function absolutely needs a LowLevelGraphicsSoftwareRenderer, one could still create another LookAndFeel::createLowLevelGraphicsSoftwareRenderer() function?

Actually, that’s a bit of a problem… That code is in the juce_graphics module, which doesn’t depend on the juce_gui module that contains the look and feel stuff, and I can’t introduce such a big module dependency just for that. I haven’t time to think about other approaches right now, but if you can think of anything that doesn’t require huge changes, let me know.

Maybe it’s because the LookAndFeel class isn’t the right place to put this kind of stuff and you could create an extra class for that purpose? Just an idea, dunno if you feel the same way.

Something like a global GraphicsContextFactory?

Globals are bad, and you’d need to give me a far more compelling reason to add something like that, I’m afraid.

Up to you. Let me know when you brewed something…

What about adding an opaque class for that, like:
class GraphicContextCreator
{
virtual GraphicContext * createContext(Component * component);
static GraphicContextCreator * getInstance();
static GraphicContextCreator * setDefaultContextCreator();
};

Zamrate, you could have LookAndFeel class to derive from that class and register itself as the default context creator, and Jules, you don’t need to cross the graphics module boundary, the class interface is so simple, it can be declared in the graphics module (and I guess the gui module depends on the graphic one).

Good idea.

Jules, what do you think about X-Ryl669’s suggestion?

Yeah… not really keen, it’s still a global variable. I’m really anti-globals (anti-globalisation?) these days, and this seems like way too much of a niche edge-case scenario to be worth adding one.

Can you do it somehow by having a custom image type that returns your special context?

There’s no getting around globals in library code, and Juce is a library / framework no matter how you try to dress it up with modules. Pretending that it is possible to get rid of all the globals in Juce is a pipe dream - and not even worth it.

At the very core of a Juce application is the application instance global variable, what’s wrong with having the LookAndFeel pointer be a part of the application instance, and allowing for a way to override the graphics context creation?

Oh, I totally agree, and obviously there are all sorts of globals in the code where necessary. I just don’t want to go handing them too freely for things like this, which is probably only of interest to a tiny number of people (in fact, probably only one person).

Why not just make it a virtual member of the JUCEApplication base class whose default implementation is to return “new LowLevelGraphicsContext”? There’s always an application instance (I think)…or no?

Well, no, in fact there’s no reason why the graphics module should expect an application instance to exist, (and it’s not really an appropriate place for anything like that anyway).

I was under the impression that in order to do anything with Juce, whether you are building a stand-alone executable, or a DLL / plugin instance, you have to have the magic lines which create the “application” instance…what was it again? Ah yes START_JUCE_APPLICATION?

WHOOPS oh yes, it just dawned on me, you are right. The more appropriate solution would be making Image a class template, with template parameters allowing for customization of the creation of the context but I’m guessing you would sooner add a global variable than factor out the Image class so that the context creation happens through a template parameter (with a default argument that preserves the existing behavior of calling new LowLevelGraphicsSoftwareRenderer or what not).

Well, no… A plugin doesn’t have an application object, and neither does a command-line app.

[quote]Yeah… not really keen, it’s still a global variable. I’m really anti-globals (anti-globalisation?) these days, and this seems like way too much of a niche edge-case scenario to be worth adding one.

Can you do it somehow by having a custom image type that returns your special context?[/quote]

Speaking politically, I’m also anti-globalisation, but I don’t see the problem here. It’s not like you’re wanting to use 3 different software renderers in 1 application or 1 plugin (DLL) anyway, or do you want to?
Also, how could I create a custom image-type and return that special context, when the very problem is that JUCE has no proper support for 3rd party renderers? This very function gets used in JUCE itself when drawing TabbedButtonBars, AlertWindows(the ? in the circle is not shown), and I assume some more. The only way around would be to start writing own AlertWindow/TabbedButtonBar classes. You talk of an edge-case, but people have been nagging for YEARS about the bad font rendering and the sometimes slow rendering speed in JUCE, and you kept saying for years it was fine, so no wonder companies are forced to take their own steps to solve the problem. I wouldn’t be surprised to see a lot more renderers coming up as soon as this is all well implemented. So please, let’s try to all find a solution to this, I’m sure with a bit of good will it’s possible.

i’ve already had problems like that in the past, where i was writing my own opengl renderer and had no chance to use any font in there.
it’s worth nothing to have the best organised classes and modularised codebase in the library if there is no chance to stick in a preferred rendering code. What’s the point in having virtual methods in LowLevelSoftwareRenderer if there is no method to exchange it with a subclass of preference ? sometimes juce is so illogical…

If you will notice, the only area where Juce is weak is the user interface Components. They are starting to show their age (especially on hand-helds). The good news is that nothing stops you from making your own controls, starting with the Juce equivalent as the starting point. Don’t like the juce::ToolbarButtonStrip? Make your own…