Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Rotate text with transformations

This thread is locked; no one can reply to it. rss feed Print
Rotate text with transformations
JurekGP
Member #15,891
February 2015

I want to rotate some string and I'm wondering how I can do it best. I found this topic: https://www.allegro.cc/forums/thread/605671
So, how we can see there are two options. Draw to another bitmap, or use transformations.
On begin, I thought that draw to another bitmap will be easier, but I haven't done it before. Next I found example ex_transform.c, on this page, and I tried with it.
I commented what I don't need now, and wrote something like this: http://wklej.org/id/1762201/

Because transformations are for me completly new component, I don't know exactly what I do, so I can't control this. I've never drawn on two different buffers before. Sample text is drawing about this 90 degress what I want in my destination project.
But why my sample bitmap is cut which I draw in 177th line? I guess this is about drawing on two others buffers. First physically "buffer", and second this is bitmap "overlay".
These three lines (175-177) are correct? I think no, because I wrote coordinates (20, 20), but they are bigger...

Maybe easier will be draw this text to another bitmap, and then just rotate it?

Hi! I'm Pole and my english is not very well. So, please understanding to me. :)

Edgar Reynaldo
Member #8,592
May 2007
avatar

To use a transform you would probably only need a rotation and a translation transform, like so :

#SelectExpand
1ALLEGRO_TRANSFORM t; 2al_identity_transform(&t); 3 4const char* str = "MyRotatedString"; 5 6int tw = al_get_text_width(font , str); 7int th = al_get_font_line_height(font); 8 9// center x and y for text destination 10int cx = 400; 11int cy = 300; 12 13al_rotate_transform(&t , M_PI/2.0f); 14al_translate_transform(&t , cx , cy); 15 16al_use_transform(&t); 17al_draw_textf(font , al_map_rgba(255,255,255,255) , 0 , 0 , ALLEGRO_ALIGN_CENTER, 18 "%s" , str);

jmasterx
Member #11,410
October 2009

I ended up doing:

  int GraphicsContext::drawRotatedText( const std::string& text,agui::Font* font,const agui::Color& color, int x, int y, float deg, int flags )
  {
    int fx = font->getTextWidth(text) / 2;
    int fy = font->getLineHeight() / 2;
    m_transform.identity();
    m_transform.translate(-fx,-fy);
    m_transform.rotate(deg);
    m_transform.translate(x,y);
    useTransform(m_transform);
    drawText(text,font,color,0,0,flags);
    resetTransform();
    return fx * 2;
  }

Taken from my GraphicsContext:

#SelectExpand
1#include "Game/Engine/GraphicsContext.hpp" 2#include "Agui/Backends/Allegro5/Allegro5Font.hpp" 3 4namespace cge 5{ 6 GraphicsContext::GraphicsContext(void) 7 :m_shader(NULL),m_tripleBuffer(false), 8 m_buffer(NULL),m_needsFlip(false) 9 { 10 black = al_map_rgb(0,0,0); 11 } 12 13 GraphicsContext::~GraphicsContext(void) 14 { 15 if(m_buffer) 16 { 17 delete m_buffer; 18 m_buffer = NULL; 19 } 20 } 21 22 void GraphicsContext::drawSprite( Sprite* sprite, float x, float y, int flags ) 23 { 24 al_draw_bitmap(sprite->getBitmap(),x,y,flags); 25 } 26 27 void GraphicsContext::drawTintedSprite( Sprite* sprite, const Color& tint, float x, float y, int flags ) 28 { 29 al_draw_tinted_bitmap(sprite->getBitmap(),tint.getColor(),x,y,flags); 30 } 31 32 void GraphicsContext::drawSpriteRegion( Sprite* sprite, float sourceX, float sourceY, float sourceWidth, float sourceHeight, float x, float y, int flags ) 33 { 34 al_draw_bitmap_region( 35 sprite->getBitmap(), 36 sourceX, 37 sourceY, 38 sourceWidth, 39 sourceHeight, 40 x, 41 y, 42 flags); 43 } 44 45 void GraphicsContext::drawTintedSpriteRegion( Sprite* sprite,const Color& tint, float sourceX, float sourceY, float sourceWidth, float sourceHeight, float x, float y, int flags ) 46 { 47 al_draw_tinted_bitmap_region( 48 sprite->getBitmap(), 49 tint.getColor(), 50 sourceX, 51 sourceY, 52 sourceWidth, 53 sourceHeight, 54 x, 55 y, 56 flags); 57 } 58 59 void GraphicsContext::drawRotatedSprite( Sprite* sprite, float centerX, float centerY, float x, float y, float radAngle, int flags ) 60 { 61 al_draw_rotated_bitmap( 62 sprite->getBitmap(), 63 centerX, 64 centerY, 65 x, 66 y, 67 radAngle, 68 flags); 69 } 70 71 void GraphicsContext::drawTintedRotatedSprite( Sprite* sprite, const Color& tint, float centerX, float centerY, float x, float y, float radAngle, int flags ) 72 { 73 al_draw_tinted_rotated_bitmap( 74 sprite->getBitmap(), 75 tint.getColor(), 76 centerX, 77 centerY, 78 x, 79 y, 80 radAngle, 81 flags); 82 } 83 84 void GraphicsContext::drawScaledRotatedSprite( Sprite* sprite, float centerX, float centerY, float x, float y, float xScale, float yScale, float radAngle, int flags ) 85 { 86 al_draw_scaled_rotated_bitmap( 87 sprite->getBitmap(), 88 centerX, 89 centerY, 90 x, 91 y, 92 xScale, 93 yScale, 94 radAngle, 95 flags); 96 } 97 98 void GraphicsContext::drawTintedScaledRotatedSprite( Sprite* sprite, const Color& tint, float centerX, float centerY, float x, float y, float xScale, float yScale, float radAngle, int flags ) 99 { 100 al_draw_tinted_scaled_rotated_bitmap( 101 sprite->getBitmap(), 102 tint.getColor(), 103 centerX, 104 centerY, 105 x, 106 y, 107 xScale, 108 yScale, 109 radAngle, 110 flags); 111 } 112 113 void GraphicsContext::drawScaledSprite( Sprite *sprite, float sourceX, float sourceY, float sourceWidth, float sourceHeight, float x, float y, float destinationWidth, float destinationHeight, int flags ) 114 { 115 al_draw_scaled_bitmap( 116 sprite->getBitmap(), 117 sourceX, 118 sourceY, 119 sourceWidth, 120 sourceHeight, 121 x, 122 y, 123 destinationWidth, 124 destinationHeight, 125 flags 126 ); 127 } 128 129 void GraphicsContext::clear() 130 { 131 al_clear_to_color(black); 132 } 133 134 void GraphicsContext::clear( const Color& color ) 135 { 136 al_clear_to_color(color.getColor()); 137 } 138 139 void GraphicsContext::clearTransparent() 140 { 141 al_clear_to_color(al_map_rgba(0,0,0,0)); 142 } 143 144 void GraphicsContext::setTarget( Sprite* sprite ) 145 { 146 al_set_target_bitmap(sprite->getBitmap()); 147 } 148 149 void GraphicsContext::setTargetToBackbuffer() 150 { 151 al_set_target_bitmap(al_get_backbuffer(al_get_current_display())); 152 } 153 154 void GraphicsContext::holdDrawing() 155 { 156 al_hold_bitmap_drawing(true); 157 } 158 159 void GraphicsContext::unholdDrawing() 160 { 161 al_hold_bitmap_drawing(false); 162 } 163 164 void GraphicsContext::flipDisplay() 165 { 166 m_needsFlip = true; 167 168 } 169 170 void GraphicsContext::setClippingRect( int x, int y, int w, int h ) 171 { 172 al_set_clipping_rectangle(x,y,w,h); 173 } 174 175 void GraphicsContext::getClippingRect( int&x,int&y,int&w,int&h ) 176 { 177 al_get_clipping_rectangle(&x,&y,&w,&h); 178 } 179 180 void GraphicsContext::drawTintedScaledSprite( Sprite *sprite,const Color & color, float sourceX, float sourceY, float sourceWidth, float sourceHeight, float x, float y, float destinationWidth, float destinationHeight, int flags ) 181 { 182 al_draw_tinted_scaled_rotated_bitmap(sprite->getBitmap(), 183 color.getColor(),sourceWidth / 2, sourceHeight / 2,x + (destinationWidth / 2),y + (destinationHeight / 2),destinationWidth / (float)sourceWidth,destinationHeight / (float)sourceHeight,0.0f,0); 184 } 185 186 void GraphicsContext::drawText( 187 const std::string& text,Font* font,const Color& color, int x, int y, int flags ) 188 { 189 al_draw_text(font->getFont(), 190 color.getColor(), 191 x,y,flags,text.c_str()); 192 } 193 194 void GraphicsContext::drawText( 195 const std::string& text,agui::Font* font,const agui::Color& color, int x, int y, int flags ) 196 { 197 al_draw_text(((agui::Allegro5Font*)font)->getFont(), 198 al_map_rgba_f(color.getR(),color.getG(),color.getB(),color.getA()), 199 x,y,flags,text.c_str()); 200 } 201 202 void GraphicsContext::drawFilledRectangle( int x, int y, int w, int h,const agui::Color& color ) 203 { 204 al_draw_filled_rectangle(x,y,x + w,y + h,al_map_rgba_f(color.getR(),color.getG(),color.getB(),color.getA())); 205 } 206 207 void GraphicsContext::setShader( Shader* shader ) 208 { 209 m_shader = shader; 210 } 211 212 void GraphicsContext::resetTransform() 213 { 214 ALLEGRO_TRANSFORM t; 215 al_identity_transform(&t); 216 al_use_transform(&t); 217 } 218 219 void GraphicsContext::useTransform( Transformation& t ) 220 { 221 al_use_transform(&t.getTransform()); 222 } 223 224 int GraphicsContext::drawRotatedText( const std::string& text,agui::Font* font,const agui::Color& color, int x, int y, float deg, int flags ) 225 { 226 int fx = font->getTextWidth(text) / 2; 227 int fy = font->getLineHeight() / 2; 228 m_transform.identity(); 229 m_transform.translate(-fx,-fy); 230 m_transform.rotate(deg); 231 m_transform.translate(x,y); 232 useTransform(m_transform); 233 drawText(text,font,color,0,0,flags); 234 resetTransform(); 235 return fx * 2; 236 } 237 238 void GraphicsContext::begin() 239 { 240 if(isBuffering()) 241 { 242 resetTransform(); 243 } 244 245 } 246 247 void GraphicsContext::resizeBuffer(int w, int h) 248 { 249 if(isBuffering()) 250 { 251 delete m_buffer; 252 m_buffer = new Sprite(w,h); 253 } 254 } 255 256 bool GraphicsContext::isBuffering() const 257 { 258 return m_tripleBuffer; 259 } 260 261 void GraphicsContext::setBuffering( bool buffering ) 262 { 263 m_tripleBuffer = buffering; 264 delete m_buffer; 265 m_buffer = NULL; 266 267 if(buffering) 268 { 269 resizeBuffer(al_get_display_width(al_get_current_display()) 270 ,al_get_display_height(al_get_current_display())); 271 } 272 } 273 274 void GraphicsContext::end() 275 { 276 if(m_needsFlip) 277 { 278 m_needsFlip = false; 279 al_flip_display(); 280 } 281 282 } 283 284 void GraphicsContext::setTargetToBuffer() 285 { 286 setTarget(m_buffer); 287 } 288 289 Sprite* GraphicsContext::getBuffer() 290 { 291 return m_buffer; 292 } 293}

and Transformation:

#SelectExpand
1Transformation::Transformation(void) 2{ 3 identity(); 4} 5 6Transformation::~Transformation(void) 7{ 8} 9 10ALLEGRO_TRANSFORM& Transformation::getTransform() 11{ 12 return m_transform; 13} 14 15void Transformation::identity() 16{ 17 al_identity_transform(&m_transform); 18} 19 20void Transformation::translate( float x, float y ) 21{ 22 al_translate_transform(&m_transform,x,y); 23} 24 25void Transformation::rotate( float deg ) 26{ 27 al_rotate_transform(&m_transform,deg); 28} 29 30void Transformation::scale( float x, float y ) 31{ 32 al_scale_transform(&m_transform,x,y); 33}

Edgar Reynaldo
Member #8,592
May 2007
avatar

JurekGP
Member #15,891
February 2015

Thanks you both! Now I'm correctly rotating this text how I want. ;)
Edgar Reynaldo
Your simply example was very helpful.
jmasterx
Your code let me do it in one, valid detail. Agui API is very interesting. When I will have time, I try it. ;)

But in my destination project this text is piece of something what is scrolling. So I must scale it too. In local y axis.
Until now, to testing, I had just bitmap and scrolling was very easy. I don't know how I can use function al_scale_transform(), so one more question. How I can scale this transformated string? I don't think so, just one line with this said function, will be all.

1. normal state
fe7b9bc8559b1.jpg
2. when is scrolling
e86aae9344352.jpg

Hi! I'm Pole and my english is not very well. So, please understanding to me. :)

anto80
Member #3,230
February 2003
avatar

The transformations are combined in the order of the function invocations. Thus to create a transformation that first rotates a point and then translates it, you would (starting with an identity transformation) call al_rotate_transform and then al_translate_transform. This approach is opposite of what OpenGL uses but similar to what Direct3D uses.

You may also look at this thread: https://www.allegro.cc/forums/thread/614764

___________
Currently working on his action/puzzle game CIPHER PUSHER : Blocks/Vortexes/Seafood! Facebook - Twitter - webpage

Go to: