Drawing only selected part of text.

Started by
12 comments, last by Evil Steve 14 years, 10 months ago
Hello. I'm calling DrawText function of LPD3DXFONT with DT_CALCRECT flag to get it's width in pixels. Everything is fine. Now the problem: I want to draw only selected part of the string to screen. For example I want to draw from 80 pixel to the last one so I can trim some longs texts. How to do this?
Advertisement
You have a few options, but by far the simplest is using IDirect3DDevice9::SetScissorRect(). Don't forget to reset it after drawing the text.
This function looks like it's exactly what I want, unfortunately I can't get it to work.

I'm using it like that:

m_pD3Ddev->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);

char tekst[255]; sprintf(tekst, "%s", Winamp.GetTrackTitle());
DrawPlayerTitleTextD3D(PlayerX+12, PlayerY+4, D3DCOLOR_ARGB(255, 255, 255, 255), false, tekst); //This function draws text using ID3DXFONT and a sprite
m_pD3Ddev->SetScissorRect(&TitleRect); //TitleRect is the rect given by DT_CALCRECT in DrawPlayerTitleTextD3D

m_pD3Ddev->SetRenderState(D3DRS_SCISSORTESTENABLE , FALSE);


If I understand the code above correctly, it should erase everything drawn by DrawPlayerTitleTextD3D. It does nothing.
Quote:Original post by danielw89
This function looks like it's exactly what I want, unfortunately I can't get it to work.

I'm using it like that:

m_pD3Ddev->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);

char tekst[255]; sprintf(tekst, "%s", Winamp.GetTrackTitle());
DrawPlayerTitleTextD3D(PlayerX+12, PlayerY+4, D3DCOLOR_ARGB(255, 255, 255, 255), false, tekst); //This function draws text using ID3DXFONT and a sprite
m_pD3Ddev->SetScissorRect(&TitleRect); //TitleRect is the rect given by DT_CALCRECT in DrawPlayerTitleTextD3D

m_pD3Ddev->SetRenderState(D3DRS_SCISSORTESTENABLE , FALSE);


If I understand the code above correctly, it should erase everything drawn by DrawPlayerTitleTextD3D. It does nothing.
Not quite. You need to set it before drawing, not after. Additionally, because ID3DXFont changes the device state and probably disables the scissor rect, you'll probably need to pass a valid ID3DXSprite to ID3DXFont::DrawText(), and call SetScissorRect() after the ID3DXSprite::Begin() call but before ID3DXFont::DrawText().
Thanks for your reply, but it still doesn't work. Here's what I did:

I moved the calls associated with SetScissorRect() into my drawing function, now it looks like that:
m_pSprite->Begin(D3DXSPRITE_ALPHABLEND);//a few lines of code that isn't important nowpFont->DrawText(m_pSprite, logbuf, -1, &rct, DT_CALCRECT, dwColor);TitleRect = rct;pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);pDevice->SetScissorRect(&TitleRect);pFont->DrawText(m_pSprite, logbuf, -1, &rct, DT_NOCLIP, dwColor); pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE , FALSE);m_pSprite->End();


Probably a stupid mistake, but I can't figure it out.
Quote:Original post by danielw89
Thanks for your reply, but it still doesn't work. Here's what I did:

I moved the calls associated with SetScissorRect() into my drawing function, now it looks like that:

[snip]

Probably a stupid mistake, but I can't figure it out.
DT_CALCRECT will cause the rect to be expanded to multiple lines I believe - you probably want to set the rect to the area you want the text in, not the area ID3DXFont says the text requires.
Quote:Original post by Evil Steve
DT_CALCRECT will cause the rect to be expanded to multiple lines I believe - you probably want to set the rect to the area you want the text in, not the area ID3DXFont says the text requires.


I'm a bit confused now. Sorry, I'm still a newbie.
Let's say rect given by DT_CALCRECT is named Rect.
Rect.bottom - Rect.top will give height of the text. Only one line. It's 13 pixels in my program.

Now the rect to be scissored: Anything I put there, even constant values... nothing gets cut.
Quote:Original post by danielw89
Quote:Original post by Evil Steve
DT_CALCRECT will cause the rect to be expanded to multiple lines I believe - you probably want to set the rect to the area you want the text in, not the area ID3DXFont says the text requires.


I'm a bit confused now. Sorry, I'm still a newbie.
Let's say rect given by DT_CALCRECT is named Rect.
Rect.bottom - Rect.top will give height of the text. Only one line. It's 13 pixels in my program.

Now the rect to be scissored: Anything I put there, even constant values... nothing gets cut.
From the docs for ID3DXFont::DrawText:
Quote:DT_CALCRECT
Determines the width and height of the rectangle. If there are multiple lines of text, ID3DXFont::DrawText uses the width of the rectangle pointed to by the pRect parameter and extends the base of the rectangle to bound the last line of text. If there is only one line of text, ID3DXFont::DrawText modifies the right side of the rectangle so that it bounds the last character in the line. In either case, ID3DXFont::DrawText returns the height of the formatted text but does not draw the text.
So what is the rect you're passing in to start with? I'm also not sure how ID3DXFont determines if there's multiple lines; I suspect it uses the DT_SINGLELINE flag rather than parsing the string (Since that's what the GDI DrawText() function does).
The rect I pass to ID3DXFONT::DrawText():
    RECT rct;       rct.left     = x - 1;       rct.right    = 0;    rct.top      = y - 1 ;       rct.bottom   = 0;

Variables x and y have values from my function's arguments(declaration looks like that: DrawPlayerTitleTextD3D([...] int x, int y [...])
They have to be dynamic because I want to move my text in the program's runtime.
Quote:Original post by danielw89
The rect I pass to ID3DXFONT::DrawText():
    RECT rct;       rct.left     = x - 1;       rct.right    = 0;    rct.top      = y - 1 ;       rct.bottom   = 0;

Variables x and y have values from my function's arguments(declaration looks like that: DrawPlayerTitleTextD3D([...] int x, int y [...])
They have to be dynamic because I want to move my text in the program's runtime.
DT_CALCRECT will expand the right edge of the rect to some value >= x-1, but leave the bottom value. That means that your rect is inside out when you pass it to SetScissorRect - the "top" value needs to be < the "bottom" value.

You could always try using a scissor rect of (0, 0) to (400,300) or some value that you're sure intersects your text.

This topic is closed to new replies.

Advertisement