I only added drawing of the background. The rest is directly from your repo.
draw text with transparent background on wxBitmap
Re: draw text with transparent background on wxBitmap
- Attachments
-
- checkers.png (214 Bytes) Viewed 2120 times
-
- svg_panel.h
- (1.01 KiB) Downloaded 166 times
-
- svg_panel.cpp
- (5.33 KiB) Downloaded 172 times
Use the source, Luke!
Re: draw text with transparent background on wxBitmap
Hi, doublemax, my question still remains. I just looked at your code, for drawing the text, they are still drawn on the decice context, what I need is draw on the wxBitmap. Because someone in the wx-dev forum would like to draw svg text for the toolbar icon.
Thanks.
Re: draw text with transparent background on wxBitmap
Yeah, sorry about that, didn't check the code again, i thought that version already rendered into the bitmap.ollydbg23 wrote: ↑Sat Nov 26, 2022 2:50 am Hi, doublemax, my question still remains. I just looked at your code, for drawing the text, they are still drawn on the decice context, what I need is draw on the wxBitmap. Because someone in the wx-dev forum would like to draw svg text for the toolbar icon.
The problem is that wxDC under Windows can't handle transparency, in this particular case, you can't draw into the parts of a bitmap that are transparent. You'll need to change the code to use wxGraphicsContext instead (just for the text rendering).
Use the source, Luke!
Re: draw text with transparent background on wxBitmap
Hi, thanks for the reply.
I just follow your advice and use the wxGraphicsContext class to draw the text, but unluckily, the font is still missing, see my change of the function OnPaint(). Please note that the code I used was followed from the way mentioned here: Clearing a transparent wxGraphicsContext? (Or this discussion wxGraphicsContex Text Drawing, they are mainly the same method)
I just follow your advice and use the wxGraphicsContext class to draw the text, but unluckily, the font is still missing, see my change of the function OnPaint(). Please note that the code I used was followed from the way mentioned here: Clearing a transparent wxGraphicsContext? (Or this discussion wxGraphicsContex Text Drawing, they are mainly the same method)
Code: Select all
void SVGPanel::OnPaint(wxPaintEvent &event)
{
wxAutoBufferedPaintDC dc(this);
dc.SetBrush( *wxWHITE_BRUSH );
dc.SetPen( *wxWHITE_PEN );
dc.DrawRectangle( 0, 0, GetClientSize().x, GetClientSize().y );
if( m_svg_image!=NULL )
{
double svg_ratio = m_svg_image->width / m_svg_image->height;
double panel_ratio = (double)GetClientSize().x / GetClientSize().y;
int render_width = 0;
int render_height = 0;
if( svg_ratio > panel_ratio )
{
render_width = GetClientSize().x;
render_height = svg_ratio * GetClientSize().y;
} else {
render_width = (double)GetClientSize().y * svg_ratio;
render_height = GetClientSize().y;
}
if (render_width == 0 || render_height == 0)
return;
if( !m_bitmap.IsOk() || render_width != m_bitmap.GetWidth() || render_height != m_bitmap.GetHeight() )
{
m_bitmap.Create(render_width, render_height, 32);
m_bitmap.UseAlpha(true);
NSVGrasterizer *rast = nsvgCreateRasterizer();
unsigned char *image_buffer = (unsigned char *)malloc(render_width*render_height*4);
float scale = (float)render_width / m_svg_image->width;
m_Scale = scale;
//wxLogDebug("rasterizing image %d x %d (scale=%.2f)", render_width, render_height, scale);
//printf("rasterizing image %d x %d (scale=%.2f)", render_width, render_height, scale);
nsvgRasterize(rast, m_svg_image, 0,0,scale, image_buffer, render_width, render_height, render_width*4);
PixelData bmdata(m_bitmap);
PixelData::Iterator dst(bmdata);
unsigned char *source_data = image_buffer;
for(int y=0; y<m_bitmap.GetHeight(); y++)
{
dst.MoveTo(bmdata, 0, y);
for(int x=0; x<m_bitmap.GetWidth(); x++)
{
const unsigned char alpha = source_data[3];
dst.Blue() = source_data[2] * alpha / 255;
dst.Green() = source_data[1] * alpha / 255;
dst.Red() = source_data[0] * alpha / 255;
dst.Alpha() = alpha;
dst++;
source_data += 4;
}
}
nsvgDeleteRasterizer(rast);
free(image_buffer);
// here the m_bitmap(created by m_bitmap.Create(render_width, render_height, 32)) is ready
// but it does not contains any text label information, so we have to use wxMemoryDC to
// draw text on the bitmap
wxMemoryDC memDC(m_bitmap);
// Clearing a transparent wxGraphicsContext? - wxWidgets Discussion Forum — https://forums.wxwidgets.org/viewtopic.php?t=48970&p=210477
wxGraphicsContext* gc = wxGraphicsContext::Create(memDC);
gc->SetPen(*wxRED_PEN);
gc->SetBrush(*wxTRANSPARENT_BRUSH);
for (TextLabel &a : m_TextLabels)
{
wxFont font(wxFontInfo(a.fontSize*m_Scale/1.3333).FaceName(a.family).AntiAliased(true));
gc->SetFont(font, *wxBLACK);
//gc->SetTextForeground(*wxRED);
//gc->SetTextBackground(*wxGREEN);
// size calculation
wxDouble w, h;
wxDouble descent;
gc->GetTextExtent(a.label, &w, &h, &descent);
gc->DrawText(a.label, a.x*m_Scale, a.y*m_Scale - h + descent);
}
delete gc;
memDC.SelectObject(wxNullBitmap);
}
if( m_bitmap.IsOk() )
{
dc.DrawBitmap( m_bitmap, 0, 0, true );
//m_bitmap.SaveFile( "d:\\_nano_svg_test.png", wxBITMAP_TYPE_PNG );
}
#if 0 // disable drawing the text labels on DC, we just need to build it on bitmap
// show text labels on top of the bitmap
for (TextLabel &a : m_TextLabels)
{
// The coordinates refer to the top-left corner of the rectangle bounding the string.
// See GetTextExtent() for how to get the dimensions of a text string,
// which can be used to position the text more precisely
// for svg text, its x,y is defined as: x: The x coordinate of the starting point of the text baseline.
// so generally the left bottom corner of the first character
//wxFont font(a.fontSize*4*g_Scale, wxROMAN, wxNORMAL, wxLIGHT, false, _T("Times New Roman"));
// 2022-04-10 point size is in pt unit, we have to convert it to px unit
// One point(pt) is the equivalent of 1.333(3) pixels(px)
wxFont font(wxFontInfo(a.fontSize*m_Scale/1.3333).FaceName(a.family).AntiAliased(true));
dc.SetFont(font);
// size calculation
wxCoord w, h;
wxCoord descent;
dc.GetTextExtent(a.label, &w, &h, &descent);
dc.DrawText(a.label, a.x*m_Scale, a.y*m_Scale - h + descent);
} //for (TextLabel &a : m_TextLabels)
#endif
} //if( m_svg_image!=NULL )
};
Re: draw text with transparent background on wxBitmap
This worked for me:
Without the wxANTIALIAS_NONE you get some ugly black edged around the text.
Code: Select all
// draw text on top
wxGraphicsContext *gc = wxGraphicsContext::Create( m_bitmap );
gc->SetAntialiasMode( wxANTIALIAS_NONE );
for (TextLabel &a : m_TextLabels)
{
// The coordinates refer to the top-left corner of the rectangle bounding the string.
// See GetTextExtent() for how to get the dimensions of a text string,
// which can be used to position the text more precisely
// for svg text, its x,y is defined as: x: The x coordinate of the starting point of the text baseline.
// so generally the left bottom corner of the first character
//wxFont font(a.fontSize*4*g_Scale, wxROMAN, wxNORMAL, wxLIGHT, false, _T("Times New Roman"));
// 2022-04-10 point size is in pt unit, we have to convert it to px unit
// One point(pt) is the equivalent of 1.333(3) pixels(px)
wxGraphicsFont gfont = gc->CreateFont( wxFont(wxFontInfo(a.fontSize*m_Scale/1.3333).FaceName(a.family)), *wxRED );
gc->SetFont(gfont);
// size calculation
wxDouble w, h;
wxDouble descent;
gc->GetTextExtent(a.label, &w, &h, &descent);
gc->DrawText(a.label, a.x*m_Scale, 12 + a.y*m_Scale - h + descent);
} //for (TextLabel &a : m_TextLabels)
delete gc;
}
if( m_bitmap.IsOk() )
{
dc.DrawBitmap( m_bitmap, 0, 0, true );
}
Use the source, Luke!
- doublemax@work
- Super wx Problem Solver
- Posts: 474
- Joined: Wed Jul 29, 2020 6:06 pm
- Location: NRW, Germany
Re: draw text with transparent background on wxBitmap
Code: Select all
12 + a.y*m_Scale
Re: draw text with transparent background on wxBitmap
doublemax@work wrote: ↑Mon Nov 28, 2022 7:55 amYou can remove the "12" here, i just added that because i wanted the text to overlap the drawing for testing.Code: Select all
12 + a.y*m_Scale
Hi, doublemax, thanks for your help, you solved the problem!
With your new code, the wxGraphicsContext's font rendering on wxBitmap works OK now.
Yes, I do remove the "12" to let the font a litter upper like the original screen shot.
In my testing, whether I have the line here or just comment the line out has no effect here, in both of the two cases, the text(font) shows correctly.
Code: Select all
gc->SetAntialiasMode( wxANTIALIAS_NONE );
Re: draw text with transparent background on wxBitmap
Here are some news:ollydbg23 wrote: ↑Mon Nov 28, 2022 8:05 am ...
In my testing, whether I have the line here or just comment the line out has no effect here, in both of the two cases, the text(font) shows correctly.Code: Select all
gc->SetAntialiasMode( wxANTIALIAS_NONE );
In one of my PCs, I see that if the function call statement below is missing, than the edge of the text is ugly as doublemax said:
Code: Select all
gc->SetAntialiasMode( wxANTIALIAS_NONE );
So, for consistence, we need this function call.
Re: draw text with transparent background on wxBitmap
Interesting. What's the difference between these PCs, on which one does it happen, and on which one does it not?
Use the source, Luke!
Re: draw text with transparent background on wxBitmap
When comment out this line:
Code: Select all
//gc->SetAntialiasMode( wxANTIALIAS_NONE );
The ugly edge doesn't happens on a Remote desktop PC(I run the program by remote desktop client) running Win7 64bit with GeForce MX 7**.
-
- Super wx Problem Solver
- Posts: 469
- Joined: Tue Jun 20, 2006 6:47 pm
- Contact:
Re: draw text with transparent background on wxBitmap
It might be the case that the video on remote desktop is probably being compressed and the compression has the effect of smoothing out the rough edges.
Re: draw text with transparent background on wxBitmap
Hi, New Pagodi, I haven't got chance to test(sit) on the remote desktop, so I don't know whether it has smooth issue.New Pagodi wrote: ↑Thu Dec 01, 2022 8:55 pm It might be the case that the video on remote desktop is probably being compressed and the compression has the effect of smoothing out the rough edges.
But I see that the font edge is definitely depend on the size of the window it shows. My full test code is on https://github.com/asmwarrior/SvgPanel with sample code.
Here is the two image shot of the result: And if I resize the window, the font got bad! I'm not sure why. This is test on my PC(not the remote desktop PC).
EDIT 2022-12-09:
About how to generate the two screen shots, I forgot to mention that the line:
Code: Select all
gc->SetAntialiasMode(wxANTIALIAS_NONE);
As doublemax said, it looks like the bigger font will automatically have wxANTIALIAS_NONE enabled, while the small font doesn't.
Last edited by ollydbg23 on Fri Dec 09, 2022 1:54 am, edited 1 time in total.
Re: draw text with transparent background on wxBitmap
It's possible that anti-aliasing is not used at bigger font sizes.
Use the source, Luke!