raster.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*!
  2. \file lib/cairodriver/raster.c
  3. \brief GRASS cairo display driver - draw raster
  4. (C) 2007-2008 by Lars Ahlzen and the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Lars Ahlzen <lars ahlzen.com> (original contibutor)
  8. \author Glynn Clements
  9. */
  10. #include "cairodriver.h"
  11. #include <grass/glocale.h>
  12. static int src_t, src_b, src_l, src_r, src_w, src_h;
  13. static double dst_t, dst_b, dst_l, dst_r, dst_w, dst_h;
  14. static cairo_surface_t *src_surf;
  15. static unsigned char *src_data;
  16. static int src_stride;
  17. static int masked;
  18. /*!
  19. \brief Start drawing raster
  20. \param mask
  21. \param s
  22. \param d
  23. */
  24. void Cairo_begin_raster(int mask, int s[2][2], double d[2][2])
  25. {
  26. cairo_status_t status;
  27. G_debug(1, "Cairo_begin_raster: %d, %d %d %d %d, %f %f %f %f",
  28. mask,
  29. s[0][0], s[0][1], s[1][0], s[1][1],
  30. d[0][0], d[0][1], d[1][0], d[1][1]);
  31. masked = mask;
  32. /* TODO: are top and left swapped? */
  33. src_l = s[0][0];
  34. src_r = s[0][1];
  35. src_t = s[1][0];
  36. src_b = s[1][1];
  37. src_w = src_r - src_l;
  38. src_h = src_b - src_t;
  39. dst_l = d[0][0];
  40. dst_r = d[0][1];
  41. dst_t = d[1][0];
  42. dst_b = d[1][1];
  43. dst_w = dst_r - dst_l;
  44. dst_h = dst_b - dst_t;
  45. G_debug(1, " src (TBLR): %d %d %d %d, dst (TBLR) %f %f %f %f",
  46. src_t, src_b, src_l, src_r, dst_t, dst_b, dst_l, dst_r);
  47. /* create source surface */
  48. src_surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, src_w, src_h);
  49. status = cairo_surface_status(src_surf);
  50. if (status != CAIRO_STATUS_SUCCESS)
  51. #ifdef HAVE_LONG_LONG_INT
  52. G_fatal_error("Cairo_begin_raster(): %s - %s. Using rows: %d, cols: %d, cells: %lld.",
  53. _("Failed to create surface"),
  54. cairo_status_to_string (status), src_b, src_r, (long long) src_b * src_r);
  55. #else
  56. G_fatal_error("Cairo_begin_raster(): %s - %s. Using rows: %d, cols: %d, cells: %ld.",
  57. _("Failed to create surface"),
  58. cairo_status_to_string (status), src_b, src_r, (long) src_b * src_r);
  59. #endif
  60. src_data = cairo_image_surface_get_data(src_surf);
  61. src_stride = cairo_image_surface_get_stride(src_surf);
  62. }
  63. /*!
  64. \brief Draw raster row
  65. \param n number of cell
  66. \param row raster row
  67. \param red,grn,blu,nul red,green,blue and null value
  68. \return next row
  69. */
  70. int Cairo_raster(int n, int row,
  71. const unsigned char *red, const unsigned char *grn,
  72. const unsigned char *blu, const unsigned char *nul)
  73. {
  74. unsigned int *dst =
  75. (unsigned int *)(src_data + (row - src_t) * src_stride);
  76. int i;
  77. G_debug(3, "Cairo_raster: %d %d", n, row);
  78. for (i = 0; i < n; i++) {
  79. if (masked && nul && nul[i])
  80. *dst++ = 0;
  81. else {
  82. unsigned int r = red[i];
  83. unsigned int g = grn[i];
  84. unsigned int b = blu[i];
  85. unsigned int a = 0xFF;
  86. *dst++ = (a << 24) + (r << 16) + (g << 8) + (b << 0);
  87. }
  88. }
  89. return row + 1;
  90. }
  91. /*!
  92. \brief Finish drawing raster
  93. */
  94. void Cairo_end_raster(void)
  95. {
  96. G_debug(1, "Cairo_end_raster");
  97. /* paint source surface onto dstination (scaled) */
  98. cairo_save(cairo);
  99. cairo_translate(cairo, dst_l, dst_t);
  100. cairo_scale(cairo, dst_w / src_w, dst_h / src_h);
  101. cairo_surface_mark_dirty(src_surf);
  102. cairo_set_source_surface(cairo, src_surf, 0, 0);
  103. cairo_pattern_set_filter(cairo_get_source(cairo), CAIRO_FILTER_NEAREST);
  104. cairo_paint(cairo);
  105. cairo_restore(cairo);
  106. /* cleanup */
  107. cairo_surface_destroy(src_surf);
  108. ca.modified = 1;
  109. }