summaryrefslogtreecommitdiff
path: root/src/Fl_Cairo.cxx
blob: dda01f142c9ae604b66e8864858f927655015399 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//
// "$Id$"
//
// Main header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2008 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems on the following page:
//
//     http://www.fltk.org/str.php
//

#include <config.h>

#ifdef HAVE_CAIRO
#include <FL/Fl.H>
#include <FL/x.H>
#include <FL/Fl_Window.H>

// static Fl module initialization :
Fl_Cairo_State Fl::cairo_state_;	///< contains all necesary info for current cairo context mapping
// Fl cairo features implementation

/** 
    Provides a corresponding cairo context for window \a wi.
    This is needed in a draw() override if Fl::cairo_autolink_context() 
    returns false, which is the default.
    The cairo_context() does not need to be freed as it is freed every time 
    a new cairo context is created. When the program terminates,
    a call to Fl::cairo_make_current(0) will destroy any residual context.
    \note A new cairo context is not always re-created when this method
    is used. In particular, if the current graphical context and the current 
    window didn't change between two calls, the previous gc is internally kept,
    thus optimizing the drawing performances.
    Also, after this call, Fl::cairo_gc() is adequately updated with this 
    cairo  context.
    \note Only available when configure has the --enable-cairo option
    \return the valid cairo_t* cairo context associated to this window.
*/
cairo_t * Fl::cairo_make_current(Fl_Window* wi) {
    if (!wi) return NULL; // Precondition
    
    if (fl_gc==0) { // means remove current cc
	Fl::cairo_cc(0); // destroy any previous cc
	cairo_state_.window(0);
	return 0;
    }

    // don't re-create a context if it's the same gc/window couple
    if (fl_gc==Fl::cairo_state_.gc() && fl_xid(wi) == (Window) Fl::cairo_state_.window())
	return Fl::cairo_cc();

    cairo_state_.window(wi);

#if defined(USE_X11)
    return Fl::cairo_make_current(0, wi->w(), wi->h());
#else
    return Fl::cairo_make_current(fl_gc, wi->w(), wi->h());
#endif
}

/* 
    Creates transparently a cairo_surface_t object.
    gc is an HDC context in  WIN32, a CGContext* in Quartz, a display on X11
 */
static cairo_surface_t * cairo_create_surface(void * gc, int W, int H) {
# if defined(USE_X11) // X11
    return cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, W, H);
# elif   defined(WIN32)
    return cairo_win32_surface_create((HDC) gc);
# elif defined(__APPLE_QUARTZ__)
    return cairo_quartz_surface_create_for_cg_context((CGContext*) gc, W, H);
# elif defined(__APPLE_QD__)
#  error Cairo is not supported under Apple Quickdraw, please use Apple Quartz.
# else
#  error Cairo is not supported under this platform.
# endif
}

/** 
  Creates a cairo context from a \a gc only, get its window size or offscreen size if fl_window is null.
   \note Only available when configure has the --enable-cairo option
*/
cairo_t * Fl::cairo_make_current(void *gc) {
    int W=0,H=0;
#if defined(USE_X11)
    //FIXME X11 get W,H
    // gc will be the window handle here
# warning FIXME get W,H for cairo_make_current(void*)
#elif defined(__APPLE_QUARTZ__) 
    if (fl_window) {
      Rect portRect; 
      GetPortBounds(GetWindowPort( fl_window ), &portRect);
      W = portRect.right-portRect.left;
      H = portRect.bottom-portRect.top;
    } 
    else {
      W = CGBitmapContextGetHeight(fl_gc);
      H = CGBitmapContextGetHeight(fl_gc);
    }
#elif defined(WIN32)
    // we don't need any W,H for WIN32
#else
# error Cairo is not supported under this platform.
#endif
    if (!gc) {
	Fl::cairo_cc(0);
	cairo_state_.gc(0); // keep track for next time
	return 0;
    }
    if (gc==Fl::cairo_state_.gc() && fl_window== (Window) Fl::cairo_state_.window())
	return Fl::cairo_cc();
    cairo_state_.gc(fl_gc); // keep track for next time
    cairo_surface_t * s = cairo_create_surface(gc, W, H);
    cairo_t * c = cairo_create(s);
    cairo_surface_destroy(s);
    Fl::cairo_cc(c);
    return c;
}

/** 
   Creates a cairo context from a \a gc and its size 
   \note Only available when configure has the --enable-cairo option
*/
cairo_t * Fl::cairo_make_current(void *gc, int W, int H) {
  cairo_surface_t * s = cairo_create_surface(gc, W, H);
    cairo_t * c = cairo_create(s);
    cairo_surface_destroy(s);
    Fl::cairo_cc(c);
    return c;
}
#endif // HAVE_CAIRO

//
// End of "$Id$" .
//