GeClipMap and init(BaseBitmap)
-
Ah, learned something, too
-
Thanks @ferdinand, that's really helpful. Your words explain what I see.
I dug a little deeper, and since found my issue was bit-depth related. I've changed my Bitmap to 32bit now. That's fixed that part.
However, it's introduced another issue. If I put any text in the clip map it shows up as a blank rectangle full of the set colour. The text only appears if I do something like draw a FillRect() underneath it first. Is this bit-depth related as well?
Text without FillRect():
Text with FillRect():
[Note: just to put the two images above into context for you, the second one is like a 'mouse-over' effect of the first. But the text only reads in the second one, when the FillRect() is drawn 'underneath', or before, the call to TextAt().]
WP.
-
Hey @wickedp,
Yeah, that could be the case, there is some weird hacking going on in
GeClipMap
regarding the bit depth of the managed bitmap and I remember a comment warning about stuff being buggy or slow for the bit depth X (I do not recall the exact number).But I do not think that this is the case here, I assume you are using
.TextAt()
and drawing into an empty bitmap canvas. I recognized this before myself too:TextAt()
seems to need pixels it can blend into, i.e., you cannot have text over a transparent background. When I stumbled upon this a while ago, I briefly play around with SetDrawMode with little luck and then simply assumed that you cannot have text over a transparent background. I did not dig any deeper then due to lack of time, so my assumption could have been false.It depends on what you want to do here. If this is just a question out of curiosity, I would leave it at this hint of mine. If you need text over a transparent background, I could have a deeper look, but I will probably only happen next week due to time restrictions and this probably being quite time consuming to find out (
GeClipMap
is itself only a frontend interface which operates on older and more low-level types).Cheers,
Ferdinand -
Leave it with me @ferdinand, I'll dig a bit more tomorrow and over the weekend, and if no luck I'll get back to you (or I'll try a different drawing method).
I'll let you know.
WP.
-
-
OK, I had to jump through some hoops for one solution here.
I created a separate GeClipMap, just the size of the text width and height. I added the text into this in a white colour. I then iterated over this text map and if the pixel was greater than black, I blended it in with the main clip map and the text colour needed. Not an ideal solution as it involves creating another temporary clip map, but they're only the size of the text so fairly small.
While I'm on this one, is it safe to have two clip maps inside the BeginDraw() and EndDraw() functions at the same time?
WP.
-
Hey @wickedp,
great to hear that you found a solution and thank you for sharing your approach.
While I'm on this one, is it safe to have two clip maps inside the BeginDraw() and EndDraw() functions at the same time?
I am not quite sure how this is meant. Let's assume you have a
BaseBitmap
B and twoGeClipMap
instance CA and CB.- Starting or stopping drawing operations for CA will have no impact on CB and vice versa.
- You can start and stop operations on CA and then start and stop then again on CA. This can for example be useful when you want to figure out which width and height a string S has before you define the size of a drawing canvas (so that S will fit into it). This also means that you can initialize the same canvas again.
- I would not recommend opening two canvases on the same bitmap source. As far as I know, a
GeClipMap
does not acquire a lock on its managed bitmap. So, when you then try to operate the two bitmaps without access boundaries as for example running them consecutively in a thread, you might run into crashes or garbage output when they both try to write the same data.
If this does not answer your question, I would ask for a clarification on what you mean, ideally with dummy code.
Cheers,
Ferdinand -
@ferdinand said in GeClipMap and init(BaseBitmap):
Starting or stopping drawing operations for CA will have no impact on CB and vice versa
This might be the answer. But just to be sure...
The docs say that to use both Get/SetPixelRGBA() they have to be enclosed in BeginDraw/EndDraw(). So if we're handling two clip maps at the same time, for example reading from one and writing to another, can they both be 'active' between Begin/EndDraw() at the same time?
In my case, something like this:
/* pseudo code */ GeClipMap *CA = GeClipMap::Alloc()... // init CA etc. We'll draw text into this one GeClipMap *CB = GeClipMap::Alloc()... CB->init(bmp); // init this one with another Bitmap CA->BeginDraw(); CB->BeginDraw(); /* Add some text into our first clip map */ CA->SetColor(...); CA->TextAt(...); /* 'for' loop here to iterate over CA, and copy into CB if colour from CA is not black */ LONG r,g,b,a; for(int rows = 0; etc...) { for(int cols = 0; etc...) { /* Get rgba from CA */ CA->GetPixelRGBA(....); /* Check if red colour is greater than 0 */ if(r != 0) { /* Set/blend pixel colour into CB */ CB->SetRGBA(...); } } } CA->EndDraw(); CB->EndDraw();
In this case, we have to use GetPixelRGBA on the first clip map with the text, and are using SetPixelRGBA on the second clip map that's the BaseBitmap we're adding text into. They'd both be between Begin/EndDraw() at the same time in my example above. Is this OK?
For what it's worth, it seems to work in my plugin. But I want to check that it's safe to do.
WP.
-
Hey @wickedp,
Generally speaking, I would say this is safe, but I am a bit reluctant to make such a broad statement. The specific code you have posted is however definitely safe.
As stated before,
GeClipMap
is just a front-end interface with a lower-level interface sitting behind it, let us call itBackend
. Backend operates on the data managed by theGeClipMap
, i.e., when you callBackend::DrawLine
, you pass in a memory region, and it then does what it is told to do. Since each clipmap has its own managed memory unless you deliberately initialized it with the same memory, there will be no problems.But there are methods like
Backend::TextWidth
orBackend::TextAt
which then use OS resources. It seems unlikely that this will cause problems, but I cannot categorically deny it, as this then leaks into Windows, mac OS, and Linux OS code. I.e., twoGeClipMap
instances try to measure the width of a font from two threads at the same time. Something could go wrong there, depending on what the access restrictions of these OS resources are. But since we useGeClipMap
also internally a lot, a Cinema 4D is drawing a lot of text, it seems very unlikely that there is any problem with that.But your main concern seems to be if
GeClipMap
acts as a sort of singleton, i.e., that you can only have (or operate on) one instance at a time. That is not the case. You can have as many instances as you want. But when you openGeClipMap
instances on the same memory, you can obviously run into problems, when you try to operate them in parallel. But that is not the case in your code, you are running everything consecutively, so both mapsCA
andCB
could manage the same memory in this case.Cheers,
Ferdinand -
Sounds like what I'm doing should be OK then. If I run into any problems, I'll pop back in for further advice.
Thanks @ferdinand, your help is always appreciated. We can close this one.
WP.