An LGPL/GPL-licensed artwork library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

art_render_mask.c 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * art_render_mask.c: Alpha mask source for modular rendering.
  3. *
  4. * Libart_LGPL - library of basic graphic primitives
  5. * Copyright (C) 2000 Raph Levien
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Library General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Library General Public
  18. * License along with this library; if not, write to the
  19. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20. * Boston, MA 02111-1307, USA.
  21. *
  22. * Authors: Raph Levien <raph@acm.org>
  23. */
  24. #include "config.h"
  25. #include "art_render_mask.h"
  26. #include <string.h>
  27. typedef struct _ArtMaskSourceMask ArtMaskSourceMask;
  28. struct _ArtMaskSourceMask {
  29. ArtMaskSource super;
  30. ArtRender *render;
  31. art_boolean first;
  32. int x0;
  33. int y0;
  34. int x1;
  35. int y1;
  36. const art_u8 *mask_buf;
  37. int rowstride;
  38. };
  39. static void
  40. art_render_mask_done (ArtRenderCallback *self, ArtRender *render)
  41. {
  42. art_free (self);
  43. }
  44. static int
  45. art_render_mask_can_drive (ArtMaskSource *self, ArtRender *render)
  46. {
  47. return 0;
  48. }
  49. static void
  50. art_render_mask_render (ArtRenderCallback *self, ArtRender *render,
  51. art_u8 *dest, int y)
  52. {
  53. ArtMaskSourceMask *z = (ArtMaskSourceMask *)self;
  54. int x0 = render->x0, x1 = render->x1;
  55. int z_x0 = z->x0, z_x1 = z->x1;
  56. int width = x1 - x0;
  57. int z_width = z_x1 - z_x0;
  58. art_u8 *alpha_buf = render->alpha_buf;
  59. if (y < z->y0 || y >= z->y1 || z_width <= 0)
  60. memset (alpha_buf, 0, width);
  61. else
  62. {
  63. const art_u8 *src_line = z->mask_buf + (y - z->y0) * z->rowstride;
  64. art_u8 *dst_line = alpha_buf + z_x0 - x0;
  65. if (z_x0 > x0)
  66. memset (alpha_buf, 0, z_x0 - x0);
  67. if (z->first)
  68. memcpy (dst_line, src_line, z_width);
  69. else
  70. {
  71. int x;
  72. for (x = 0; x < z_width; x++)
  73. {
  74. int v;
  75. v = src_line[x];
  76. if (v)
  77. {
  78. v = v * dst_line[x] + 0x80;
  79. v = (v + (v >> 8)) >> 8;
  80. dst_line[x] = v;
  81. }
  82. else
  83. {
  84. dst_line[x] = 0;
  85. }
  86. }
  87. }
  88. if (z_x1 < x1)
  89. memset (alpha_buf + z_x1 - x0, 0, x1 - z_x1);
  90. }
  91. }
  92. static void
  93. art_render_mask_prepare (ArtMaskSource *self, ArtRender *render,
  94. art_boolean first)
  95. {
  96. ArtMaskSourceMask *z = (ArtMaskSourceMask *)self;
  97. self->super.render = art_render_mask_render;
  98. z->first = first;
  99. }
  100. /**
  101. * art_render_mask: Use an alpha buffer as a render mask source.
  102. * @render: Render object.
  103. * @x0: Left coordinate of mask rect.
  104. * @y0: Top coordinate of mask rect.
  105. * @x1: Right coordinate of mask rect.
  106. * @y1: Bottom coordinate of mask rect.
  107. * @mask_buf: Buffer containing 8bpp alpha mask data.
  108. * @rowstride: Rowstride of @mask_buf.
  109. *
  110. * Adds @mask_buf to the render object as a mask. Note: @mask_buf must
  111. * remain allocated until art_render_invoke() is called on @render.
  112. **/
  113. void
  114. art_render_mask (ArtRender *render,
  115. int x0, int y0, int x1, int y1,
  116. const art_u8 *mask_buf, int rowstride)
  117. {
  118. ArtMaskSourceMask *mask_source;
  119. if (x0 < render->x0)
  120. {
  121. mask_buf += render->x0 - x0;
  122. x0 = render->x0;
  123. }
  124. if (x1 > render->x1)
  125. x1 = render->x1;
  126. if (y0 < render->y0)
  127. {
  128. mask_buf += (render->y0 - y0) * rowstride;
  129. y0 = render->y0;
  130. }
  131. if (y1 > render->y1)
  132. y1 = render->y1;
  133. mask_source = art_new (ArtMaskSourceMask, 1);
  134. mask_source->super.super.render = NULL;
  135. mask_source->super.super.done = art_render_mask_done;
  136. mask_source->super.can_drive = art_render_mask_can_drive;
  137. mask_source->super.invoke_driver = NULL;
  138. mask_source->super.prepare = art_render_mask_prepare;
  139. mask_source->render = render;
  140. mask_source->x0 = x0;
  141. mask_source->y0 = y0;
  142. mask_source->x1 = x1;
  143. mask_source->y1 = y1;
  144. mask_source->mask_buf = mask_buf;
  145. mask_source->rowstride = rowstride;
  146. art_render_add_mask_source (render, &mask_source->super);
  147. }