Fl_Cairo.cxx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. //
  2. // "$Id: Fl_Cairo.cxx 12467 2017-09-23 14:51:00Z manolo $"
  3. //
  4. // Main header file for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2017 by Bill Spitzak and others.
  7. //
  8. // This library is free software. Distribution and use rights are outlined in
  9. // the file "COPYING" which should have been included with this file. If this
  10. // file is missing or damaged, see the license at:
  11. //
  12. // http://www.fltk.org/COPYING.php
  13. //
  14. // Please report all bugs and problems on the following page:
  15. //
  16. // http://www.fltk.org/str.php
  17. //
  18. #include <config.h>
  19. #ifdef FLTK_HAVE_CAIRO
  20. #include <FL/Fl.H>
  21. #include <FL/x.H>
  22. #include <FL/Fl_Window.H>
  23. // Cairo is currently supported for the following platforms:
  24. // Win32, Apple Quartz, X11
  25. #if defined(USE_X11) // X11
  26. # include <cairo-xlib.h>
  27. #elif defined(WIN32)
  28. # include <cairo-win32.h>
  29. #elif defined(__APPLE_QUARTZ__) // PORTME: Cairo Support
  30. # include <cairo-quartz.h>
  31. #elif defined(FL_PORTING)
  32. # pragma message "FL_PORTING: is the Cairo library available on this platform?"
  33. #else
  34. # error Cairo is not supported on this platform.
  35. #endif
  36. // static Fl module initialization :
  37. Fl_Cairo_State Fl::cairo_state_; ///< contains all necessary info for current cairo context mapping
  38. // Fl cairo features implementation
  39. // Fl_Cairo_State class impl
  40. void Fl_Cairo_State::autolink(bool b) {
  41. #ifdef FLTK_USE_CAIRO
  42. autolink_ = b;
  43. #else
  44. Fl::fatal("In Fl::autolink(bool) : Cairo autolink() feature is only "
  45. "available with the enable-cairoext configure option, now quitting.");
  46. #endif
  47. }
  48. /**
  49. Provides a corresponding cairo context for window \a wi.
  50. This is needed in a draw() override if Fl::cairo_autolink_context()
  51. returns false, which is the default.
  52. The cairo_context() does not need to be freed as it is freed every time
  53. a new cairo context is created. When the program terminates,
  54. a call to Fl::cairo_make_current(0) will destroy any residual context.
  55. \note A new cairo context is not always re-created when this method
  56. is used. In particular, if the current graphical context and the current
  57. window didn't change between two calls, the previous gc is internally kept,
  58. thus optimizing the drawing performances.
  59. Also, after this call, Fl::cairo_cc() is adequately updated with this
  60. cairo context.
  61. \note Only available when configure has the --enable-cairo option
  62. \return the valid cairo_t* cairo context associated to this window.
  63. */
  64. cairo_t * Fl::cairo_make_current(Fl_Window* wi) {
  65. if (!wi) return NULL; // Precondition
  66. if (fl_gc==0) { // means remove current cc
  67. Fl::cairo_cc(0); // destroy any previous cc
  68. cairo_state_.window(0);
  69. return 0;
  70. }
  71. // don't re-create a context if it's the same gc/window couple
  72. if (fl_gc==Fl::cairo_state_.gc() && fl_xid(wi) == (Window) Fl::cairo_state_.window())
  73. return Fl::cairo_cc();
  74. cairo_state_.window(wi);
  75. #if defined(USE_X11)
  76. return Fl::cairo_make_current(0, wi->w(), wi->h());
  77. #else
  78. return Fl::cairo_make_current(fl_gc, wi->w(), wi->h());
  79. #endif
  80. }
  81. /*
  82. Creates transparently a cairo_surface_t object.
  83. gc is an HDC context in WIN32, a CGContext* in Quartz, and
  84. a display on X11 (not used on this platform)
  85. */
  86. static cairo_surface_t * cairo_create_surface(void * gc, int W, int H) {
  87. # if defined(USE_X11)
  88. return cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, W, H);
  89. # elif defined(WIN32)
  90. return cairo_win32_surface_create((HDC) gc);
  91. # elif defined(__APPLE_QUARTZ__)
  92. return cairo_quartz_surface_create_for_cg_context((CGContext*) gc, W, H);
  93. # else
  94. # error Cairo is not supported under this platform.
  95. # endif
  96. }
  97. /**
  98. Creates a cairo context from a \a gc only, gets its window size or
  99. offscreen size if fl_window is null.
  100. \note Only available when configure has the --enable-cairo option
  101. */
  102. cairo_t * Fl::cairo_make_current(void *gc) {
  103. int W=0,H=0;
  104. #if defined(USE_X11)
  105. //FIXME X11 get W,H
  106. // gc will be the window handle here
  107. # warning FIXME get W,H for cairo_make_current(void*)
  108. #elif defined(__APPLE_QUARTZ__)
  109. if (fl_window) {
  110. W = Fl_Window::current()->w();
  111. H = Fl_Window::current()->h();
  112. }
  113. else {
  114. W = CGBitmapContextGetWidth(fl_gc);
  115. H = CGBitmapContextGetHeight(fl_gc);
  116. }
  117. #elif defined(WIN32)
  118. // we don't need any W,H for WIN32
  119. #else
  120. # error Cairo is not supported on this platform.
  121. #endif
  122. if (!gc) {
  123. Fl::cairo_cc(0);
  124. cairo_state_.gc(0); // keep track for next time
  125. return 0;
  126. }
  127. if (gc==Fl::cairo_state_.gc() &&
  128. fl_window== (Window) Fl::cairo_state_.window() &&
  129. cairo_state_.cc()!=0)
  130. return Fl::cairo_cc();
  131. cairo_state_.gc(fl_gc); // keep track for next time
  132. cairo_surface_t * s = cairo_create_surface(gc, W, H);
  133. cairo_t * c = cairo_create(s);
  134. cairo_surface_destroy(s);
  135. cairo_state_.cc(c);
  136. return c;
  137. }
  138. /**
  139. Creates a cairo context from a \a gc and its size
  140. \note Only available when configure has the --enable-cairo option
  141. */
  142. cairo_t * Fl::cairo_make_current(void *gc, int W, int H) {
  143. if (gc==Fl::cairo_state_.gc() &&
  144. fl_window== (Window) Fl::cairo_state_.window() &&
  145. cairo_state_.cc()!=0) // no need to create a cc, just return that one
  146. return cairo_state_.cc();
  147. // we need to (re-)create a fresh cc ...
  148. cairo_state_.gc(gc); // keep track for next time
  149. cairo_surface_t * s = cairo_create_surface(gc, W, H);
  150. cairo_t * c = cairo_create(s);
  151. cairo_state_.cc(c); // and purge any previously owned context
  152. cairo_surface_destroy(s);
  153. return c;
  154. }
  155. #else
  156. // just don't leave the libfltk_cairo lib empty to avoid warnings
  157. #include <FL/Fl_Export.H>
  158. FL_EXPORT int fltk_cairo_dummy() { return 1;}
  159. #endif // FLTK_HAVE_CAIRO
  160. //
  161. // End of "$Id: Fl_Cairo.cxx 12467 2017-09-23 14:51:00Z manolo $" .
  162. //