1 /////////////////////////////////////////////////////////////////////////////
3 // Author: Robert Roebling
5 // Copyright: 2000 (c) Robert Roebling
6 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
10 #pragma implementation "canvas.cpp"
13 // For compilers that support precompilation, includes "wx/wx.h".
14 #include "wx/wxprec.h"
20 #include "wx/canvas/canvas.h"
24 #include <gdk/gdkrgb.h>
25 #include "wx/gtk/win_gtk.h"
28 #define USE_FREETYPE 0
31 #include <freetype/freetype.h>
34 //----------------------------------------------------------------------------
36 //----------------------------------------------------------------------------
39 FT_Library g_freetypeLibrary
;
42 //----------------------------------------------------------------------------
44 //----------------------------------------------------------------------------
46 wxCanvasObject::wxCanvasObject( int x
, int y
, int width
, int height
)
52 m_area
.height
= height
;
58 void wxCanvasObject::Move( int x
, int y
)
68 // TODO: sometimes faster to merge into 1 Update or
69 // to break up into four
70 m_owner
->Update( old_x
, old_y
, m_area
.width
, m_area
.height
);
71 m_owner
->Update( x
, y
, m_area
.width
, m_area
.height
);
75 void wxCanvasObject::WriteSVG( wxTextOutputStream
&stream
)
79 void wxCanvasObject::Render( int clip_x
, int clip_y
, int clip_width
, int clip_height
)
83 //----------------------------------------------------------------------------
85 //----------------------------------------------------------------------------
87 wxCanvasImage::wxCanvasImage( const wxImage
&image
, int x
, int y
)
88 : wxCanvasObject( x
, y
, image
.GetWidth(), image
.GetHeight() )
94 void wxCanvasImage::Render( int clip_x
, int clip_y
, int clip_width
, int clip_height
)
96 int start_x
= wxMax( 0, clip_x
-m_area
.x
);
97 int end_x
= wxMin( m_area
.width
, clip_width
+clip_x
-m_area
.x
);
98 int start_y
= wxMax( 0, clip_y
-m_area
.y
);
99 int end_y
= wxMin( m_area
.height
, clip_height
+clip_y
-m_area
.y
);
101 if (end_x
< start_x
) return;
102 if (end_y
< start_y
) return;
104 if ((start_x
== 0) &&
106 (end_x
== m_area
.width
) &&
107 (end_y
== m_area
.height
))
109 m_owner
->GetBuffer()->Paste( m_image
, m_area
.x
, m_area
.y
);
113 wxRect
rect( start_x
, start_y
, end_x
-start_x
, end_y
-start_y
);
114 wxImage
sub_image( m_image
.GetSubImage( rect
) );
115 m_owner
->GetBuffer()->Paste( sub_image
, m_area
.x
+start_x
, m_area
.y
+start_y
);
119 void wxCanvasImage::WriteSVG( wxTextOutputStream
&stream
)
124 //----------------------------------------------------------------------------
126 //----------------------------------------------------------------------------
128 wxCanvasControl::wxCanvasControl( wxWindow
*control
)
129 : wxCanvasObject( -1, -1, -1, -1 )
135 wxCanvasControl::~wxCanvasControl()
137 m_control
->Destroy();
140 void wxCanvasControl::Move( int x
, int y
)
142 m_control
->Move( x
, y
);
145 void wxCanvasControl::UpdateSize()
147 m_control
->GetSize( &m_area
.width
, &m_area
.height
);
148 m_control
->GetPosition( &m_area
.x
, &m_area
.y
);
151 //----------------------------------------------------------------------------
153 //----------------------------------------------------------------------------
165 wxCanvasText::wxCanvasText( const wxString
&text
, int x
, int y
)
166 : wxCanvasObject( x
, y
, -1, -1 )
178 m_alpha
= new unsigned char[128*128];
179 for (int y
= 0; y
< m_area
.height
; y
++)
180 for (int x
= 0; x
< m_area
.width
; x
++)
181 m_alpha
[y
*m_area
.width
+ x
] = x
;
185 wxFaceData
*data
= new wxFaceData
;
188 int error
= FT_New_Face( g_freetypeLibrary
,
189 "~/TrueType/times.ttf",
193 error
= FT_Set_Char_Size( data
->m_face
,
201 wxCanvasText::~wxCanvasText()
204 wxFaceData
*data
= (wxFaceData
*) m_faceData
;
208 if (m_alpha
) delete [] m_alpha
;
211 void wxCanvasText::SetRGB( unsigned char red
, unsigned char green
, unsigned char blue
)
218 void wxCanvasText::SetFlag( int flag
)
223 void wxCanvasText::Render( int clip_x
, int clip_y
, int clip_width
, int clip_height
)
225 if (!m_alpha
) return;
227 wxImage
*image
= m_owner
->GetBuffer();
229 int start_x
= wxMax( 0, clip_x
-m_area
.x
);
230 int end_x
= wxMin( m_area
.width
, clip_width
+clip_x
-m_area
.x
);
231 int start_y
= wxMax( 0, clip_y
-m_area
.y
);
232 int end_y
= wxMin( m_area
.height
, clip_height
+clip_y
-m_area
.y
);
234 for (int y
= start_y
; y
< end_y
; y
++)
235 for (int x
= start_x
; x
< end_x
; x
++)
237 int alpha
= m_alpha
[y
*m_area
.width
+ x
];
240 int image_x
= m_area
.x
+x
;
241 int image_y
= m_area
.y
+y
;
244 image
->SetRGB( image_x
, image_y
, m_red
, m_green
, m_blue
);
247 int red1
= (m_red
* alpha
) / 128;
248 int green1
= (m_green
* alpha
) / 128;
249 int blue1
= (m_blue
* alpha
) / 128;
252 int red2
= image
->GetRed( image_x
, image_y
);
253 int green2
= image
->GetGreen( image_x
, image_y
);
254 int blue2
= image
->GetBlue( image_x
, image_y
);
255 red2
= (red2
* alpha
) / 128;
256 green2
= (green2
* alpha
) / 128;
257 blue2
= (blue2
* alpha
) / 128;
259 image
->SetRGB( image_x
, image_y
, red1
+red2
, green1
+green2
, blue1
+blue2
);
264 void wxCanvasText::WriteSVG( wxTextOutputStream
&stream
)
268 void wxCanvasText::CreateBuffer()
271 FT_Face face
= ((wxFaceData
*)m_faceData
)->m_face
;
272 FT_GlyphSlot slot
= face
->glyph
;
276 for (int n
= 0; n
< m_text
.Len(); n
++)
278 FT_UInt index
= FT_Get_Char_Index( face
, m_text
[n
] );
280 int error
= FT_Load_Glyph( face
, index
, FT_LOAD_DEFAULT
);
283 error
= FT_Render_Glyph( face
->glyph
, ft_render_antialias
);
286 pen_x
+= slot
->advance
.x
>> 6;
287 pen_y
+= slot
->advance
.y
>> 6;
292 //----------------------------------------------------------------------------
294 //----------------------------------------------------------------------------
296 IMPLEMENT_CLASS(wxCanvas
,wxScrolledWindow
)
298 BEGIN_EVENT_TABLE(wxCanvas
,wxScrolledWindow
)
299 EVT_CHAR( wxCanvas::OnChar
)
300 EVT_PAINT( wxCanvas::OnPaint
)
301 EVT_SIZE( wxCanvas::OnSize
)
302 EVT_IDLE( wxCanvas::OnIdle
)
303 EVT_MOUSE_EVENTS( wxCanvas::OnMouse
)
304 EVT_SET_FOCUS( wxCanvas::OnSetFocus
)
305 EVT_KILL_FOCUS( wxCanvas::OnKillFocus
)
308 wxCanvas::wxCanvas( wxWindow
*parent
, wxWindowID id
,
309 const wxPoint
&position
, const wxSize
& size
, long style
) :
310 wxScrolledWindow( parent
, id
, position
, size
, style
)
312 m_needUpdate
= FALSE
;
313 m_objects
.DeleteContents( TRUE
);
316 wxCanvas::~wxCanvas()
318 wxNode
*node
= m_updateRects
.First();
321 wxRect
*rect
= (wxRect
*) node
->Data();
323 m_updateRects
.DeleteNode( node
);
324 node
= m_updateRects
.First();
328 void wxCanvas::SetArea( int width
, int height
)
330 m_buffer
= wxImage( width
, height
);
331 SetScrollbars( 10, 10, width
/10, height
/10 );
334 void wxCanvas::Update( int x
, int y
, int width
, int height
)
338 m_updateRects
.Append(
339 (wxObject
*) new wxRect( x
,y
,width
,height
) );
341 // speed up with direct access, maybe add wxImage::Clear(x,y,w,h)
343 for (yy
= y
; yy
< y
+height
; yy
++)
344 for (xx
= x
; xx
< x
+width
; xx
++)
345 m_buffer
.SetRGB( xx
, yy
, 0, 0, 0 );
347 wxNode
*node
= m_objects
.First();
350 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
353 ww
= obj
->GetWidth();
354 hh
= obj
->GetHeight();
356 if (!obj
->IsControl()) // calc intersection !
358 obj
->Render( x
, y
, width
, height
);
365 void wxCanvas::BlitBuffer( wxDC
&dc
)
367 wxNode
*node
= m_updateRects
.First();
370 wxRect
*rect
= (wxRect
*) node
->Data();
371 wxImage
sub_image( m_buffer
.GetSubImage( *rect
) );
373 // DirectDraw here, please
376 int bpp
= wxDisplayDepth();
379 // the init code is doubled in wxImage
380 static bool s_hasInitialized
= FALSE
;
382 if (!s_hasInitialized
)
385 s_hasInitialized
= TRUE
;
390 CalcScrolledPosition( x
, y
, &x
, &y
);
392 gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow
)->bin_window
,
393 m_wxwindow
->style
->black_gc
,
395 sub_image
.GetWidth(), sub_image
.GetHeight(),
398 sub_image
.GetWidth()*3 );
402 wxBitmap
bitmap( sub_image
.ConvertToBitmap() );
403 dc
.DrawBitmap( bitmap
, rect
->x
, rect
->y
);
408 wxBitmap
bitmap( sub_image
.ConvertToBitmap() );
409 dc
.DrawBitmap( bitmap
, rect
->x
, rect
->y
);
413 m_updateRects
.DeleteNode( node
);
414 node
= m_updateRects
.First();
417 m_needUpdate
= FALSE
;
420 void wxCanvas::UpdateNow()
422 if (!m_needUpdate
) return;
424 wxClientDC
dc( this );
430 void wxCanvas::Prepend( wxCanvasObject
* obj
)
432 m_objects
.Insert( obj
);
434 obj
->SetOwner( this );
436 if (!obj
->IsControl())
437 Update( obj
->GetX(), obj
->GetY(), obj
->GetWidth(), obj
->GetHeight() );
440 void wxCanvas::Append( wxCanvasObject
* obj
)
442 m_objects
.Append( obj
);
444 obj
->SetOwner( this );
446 if (!obj
->IsControl())
447 Update( obj
->GetX(), obj
->GetY(), obj
->GetWidth(), obj
->GetHeight() );
450 void wxCanvas::Insert( size_t before
, wxCanvasObject
* obj
)
452 m_objects
.Insert( before
, obj
);
454 obj
->SetOwner( this );
456 if (!obj
->IsControl())
457 Update( obj
->GetX(), obj
->GetY(), obj
->GetWidth(), obj
->GetHeight() );
460 void wxCanvas::Remove( wxCanvasObject
* obj
)
464 int w
= obj
->GetWidth();
465 int h
= obj
->GetHeight();
466 bool ic
= obj
->IsControl();
468 m_objects
.DeleteObject( obj
);
471 Update( x
, y
, w
, h
);
474 void wxCanvas::OnPaint(wxPaintEvent
&event
)
481 wxRegionIterator
it( GetUpdateRegion() );
486 CalcUnscrolledPosition( x
, y
, &x
, &y
);
488 int w
= it
.GetWidth();
489 int h
= it
.GetHeight();
490 if (x
+ w
> m_buffer
.GetWidth())
491 w
= m_buffer
.GetWidth()-x
;
492 if (y
+ h
> m_buffer
.GetHeight())
493 h
= m_buffer
.GetHeight()-y
;
495 m_updateRects
.Append( (wxObject
*) new wxRect( x
, y
, w
, h
) );
503 void wxCanvas::OnMouse(wxMouseEvent
&event
)
505 // Propagate to objects here
508 void wxCanvas::OnSize(wxSizeEvent
&event
)
513 void wxCanvas::OnIdle(wxIdleEvent
&event
)
519 void wxCanvas::OnSetFocus(wxFocusEvent
&event
)
523 void wxCanvas::OnKillFocus(wxFocusEvent
&event
)
527 void wxCanvas::OnChar(wxKeyEvent
&event
)
532 //--------------------------------------------------------------------
534 //--------------------------------------------------------------------
536 class wxCanvasModule
: public wxModule
539 virtual bool OnInit();
540 virtual void OnExit();
543 DECLARE_DYNAMIC_CLASS(wxCanvasModule
)
546 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule
, wxModule
)
548 bool wxCanvasModule::OnInit()
551 int error
= FT_Init_FreeType( &g_freetypeLibrary
);
552 if (error
) return FALSE
;
558 void wxCanvasModule::OnExit()