gsbitops.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: gsbitops.c,v 1.8 2002/10/07 08:28:56 ghostgum Exp $ */
  14. /* Bitmap filling, copying, and transforming operations */
  15. #include "stdio_.h"
  16. #include "memory_.h"
  17. #include "gdebug.h"
  18. #include "gserror.h"
  19. #include "gserrors.h"
  20. #include "gstypes.h"
  21. #include "gsbittab.h"
  22. #include "gxbitops.h"
  23. #include "gxcindex.h"
  24. /* ---------------- Bit-oriented operations ---------------- */
  25. /* Define masks for little-endian operation. */
  26. /* masks[i] has the first i bits off and the rest on. */
  27. #if !arch_is_big_endian
  28. const bits16 mono_copy_masks[17] = {
  29. 0xffff, 0xff7f, 0xff3f, 0xff1f,
  30. 0xff0f, 0xff07, 0xff03, 0xff01,
  31. 0xff00, 0x7f00, 0x3f00, 0x1f00,
  32. 0x0f00, 0x0700, 0x0300, 0x0100,
  33. 0x0000
  34. };
  35. const bits32 mono_fill_masks[33] = {
  36. #define mask(n)\
  37. ((~0xff | (0xff >> (n & 7))) << (n & -8))
  38. mask( 0),mask( 1),mask( 2),mask( 3),mask( 4),mask( 5),mask( 6),mask( 7),
  39. mask( 8),mask( 9),mask(10),mask(11),mask(12),mask(13),mask(14),mask(15),
  40. mask(16),mask(17),mask(18),mask(19),mask(20),mask(21),mask(22),mask(23),
  41. mask(24),mask(25),mask(26),mask(27),mask(28),mask(29),mask(30),mask(31),
  42. 0
  43. #undef mask
  44. };
  45. #endif
  46. /* Fill a rectangle of bits with an 8x1 pattern. */
  47. /* The pattern argument must consist of the pattern in every byte, */
  48. /* e.g., if the desired pattern is 0xaa, the pattern argument must */
  49. /* have the value 0xaaaa (if ints are short) or 0xaaaaaaaa. */
  50. #undef chunk
  51. #define chunk mono_fill_chunk
  52. #undef mono_masks
  53. #define mono_masks mono_fill_masks
  54. void
  55. bits_fill_rectangle(byte * dest, int dest_bit, uint draster,
  56. mono_fill_chunk pattern, int width_bits, int height)
  57. {
  58. uint bit;
  59. chunk right_mask;
  60. int line_count = height;
  61. chunk *ptr;
  62. int last_bit;
  63. #define FOR_EACH_LINE(stat)\
  64. do { stat } while ( inc_ptr(ptr, draster), --line_count )
  65. dest += (dest_bit >> 3) & -chunk_align_bytes;
  66. ptr = (chunk *) dest;
  67. bit = dest_bit & chunk_align_bit_mask;
  68. last_bit = width_bits + bit - (chunk_bits + 1);
  69. if (last_bit < 0) { /* <=1 chunk */
  70. set_mono_thin_mask(right_mask, width_bits, bit);
  71. if (pattern == 0)
  72. FOR_EACH_LINE(*ptr &= ~right_mask;);
  73. else if (pattern == (mono_fill_chunk)(-1))
  74. FOR_EACH_LINE(*ptr |= right_mask;);
  75. else
  76. FOR_EACH_LINE(
  77. *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
  78. } else {
  79. chunk mask;
  80. int last = last_bit >> chunk_log2_bits;
  81. set_mono_left_mask(mask, bit);
  82. set_mono_right_mask(right_mask, (last_bit & chunk_bit_mask) + 1);
  83. switch (last) {
  84. case 0: /* 2 chunks */
  85. if (pattern == 0)
  86. FOR_EACH_LINE(*ptr &= ~mask; ptr[1] &= ~right_mask;);
  87. else if (pattern == (mono_fill_chunk)(-1))
  88. FOR_EACH_LINE(*ptr |= mask; ptr[1] |= right_mask;);
  89. else
  90. FOR_EACH_LINE(
  91. *ptr = (*ptr & ~mask) | (pattern & mask);
  92. ptr[1] = (ptr[1] & ~right_mask) | (pattern & right_mask); );
  93. break;
  94. case 1: /* 3 chunks */
  95. if (pattern == 0)
  96. FOR_EACH_LINE( *ptr &= ~mask;
  97. ptr[1] = 0;
  98. ptr[2] &= ~right_mask; );
  99. else if (pattern == (mono_fill_chunk)(-1))
  100. FOR_EACH_LINE( *ptr |= mask;
  101. ptr[1] = ~(chunk) 0;
  102. ptr[2] |= right_mask; );
  103. else
  104. FOR_EACH_LINE( *ptr = (*ptr & ~mask) | (pattern & mask);
  105. ptr[1] = pattern;
  106. ptr[2] = (ptr[2] & ~right_mask) | (pattern & right_mask); );
  107. break;
  108. default:{ /* >3 chunks */
  109. uint byte_count = (last_bit >> 3) & -chunk_bytes;
  110. if (pattern == 0)
  111. FOR_EACH_LINE( *ptr &= ~mask;
  112. memset(ptr + 1, 0, byte_count);
  113. ptr[last + 1] &= ~right_mask; );
  114. else if (pattern == (mono_fill_chunk)(-1))
  115. FOR_EACH_LINE( *ptr |= mask;
  116. memset(ptr + 1, 0xff, byte_count);
  117. ptr[last + 1] |= right_mask; );
  118. else
  119. FOR_EACH_LINE(
  120. *ptr = (*ptr & ~mask) | (pattern & mask);
  121. memset(ptr + 1, (byte) pattern, byte_count);
  122. ptr[last + 1] = (ptr[last + 1] & ~right_mask) |
  123. (pattern & right_mask); );
  124. }
  125. }
  126. }
  127. #undef FOR_EACH_LINE
  128. }
  129. /*
  130. * Similar to bits_fill_rectangle, but with an additional source mask.
  131. * The src_mask variable is 1 for those bits of the original that are
  132. * to be retained. The mask argument must consist of the requisite value
  133. * in every byte, in the same manner as the pattern.
  134. */
  135. void
  136. bits_fill_rectangle_masked(byte * dest, int dest_bit, uint draster,
  137. mono_fill_chunk pattern, mono_fill_chunk src_mask,
  138. int width_bits, int height)
  139. {
  140. uint bit;
  141. chunk right_mask;
  142. int line_count = height;
  143. chunk *ptr;
  144. int last_bit;
  145. #define FOR_EACH_LINE(stat)\
  146. do { stat } while ( inc_ptr(ptr, draster), --line_count )
  147. dest += (dest_bit >> 3) & -chunk_align_bytes;
  148. ptr = (chunk *) dest;
  149. bit = dest_bit & chunk_align_bit_mask;
  150. last_bit = width_bits + bit - (chunk_bits + 1);
  151. if (last_bit < 0) { /* <=1 chunk */
  152. set_mono_thin_mask(right_mask, width_bits, bit);
  153. right_mask &= ~src_mask;
  154. if (pattern == 0)
  155. FOR_EACH_LINE(*ptr &= ~right_mask;);
  156. else if (pattern == (mono_fill_chunk)(-1))
  157. FOR_EACH_LINE(*ptr |= right_mask;);
  158. else
  159. FOR_EACH_LINE(
  160. *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
  161. } else {
  162. chunk mask;
  163. int last = last_bit >> chunk_log2_bits;
  164. set_mono_left_mask(mask, bit);
  165. set_mono_right_mask(right_mask, (last_bit & chunk_bit_mask) + 1);
  166. mask &= ~src_mask;
  167. right_mask &= ~src_mask;
  168. switch (last) {
  169. case 0: /* 2 chunks */
  170. if (pattern == 0)
  171. FOR_EACH_LINE(*ptr &= ~mask; ptr[1] &= ~right_mask;);
  172. else if (pattern == (mono_fill_chunk)(-1))
  173. FOR_EACH_LINE(*ptr |= mask; ptr[1] |= right_mask;);
  174. else
  175. FOR_EACH_LINE(
  176. *ptr = (*ptr & ~mask) | (pattern & mask);
  177. ptr[1] = (ptr[1] & ~right_mask) | (pattern & right_mask); );
  178. break;
  179. case 1: /* 3 chunks */
  180. if (pattern == 0)
  181. FOR_EACH_LINE( *ptr &= ~mask;
  182. ptr[1] &= src_mask;
  183. ptr[2] &= ~right_mask; );
  184. else if (pattern == (mono_fill_chunk)(-1))
  185. FOR_EACH_LINE( *ptr |= mask;
  186. ptr[1] |= ~src_mask;
  187. ptr[2] |= right_mask; );
  188. else
  189. FOR_EACH_LINE( *ptr = (*ptr & ~mask) | (pattern & mask);
  190. ptr[1] =(ptr[1] & src_mask) | pattern;
  191. ptr[2] = (ptr[2] & ~right_mask) | (pattern & right_mask); );
  192. break;
  193. default:{ /* >3 chunks */
  194. int i;
  195. if (pattern == 0)
  196. FOR_EACH_LINE( *ptr++ &= ~mask;
  197. for (i = 0; i < last; i++)
  198. *ptr++ &= src_mask;
  199. *ptr &= ~right_mask; );
  200. else if (pattern == (mono_fill_chunk)(-1))
  201. FOR_EACH_LINE( *ptr++ |= mask;
  202. for (i = 0; i < last; i++)
  203. *ptr++ |= ~src_mask;
  204. *ptr |= right_mask; );
  205. else
  206. FOR_EACH_LINE(
  207. /* note: we know (pattern & ~src_mask) == pattern */
  208. *ptr = (*ptr & ~mask) | (pattern & mask);
  209. ++ptr;
  210. for (i = 0; i < last; i++, ptr++)
  211. *ptr = (*ptr & src_mask) | pattern;
  212. *ptr = (*ptr & ~right_mask) | (pattern & right_mask); );
  213. }
  214. }
  215. }
  216. #undef FOR_EACH_LINE
  217. }
  218. /* Replicate a bitmap horizontally in place. */
  219. void
  220. bits_replicate_horizontally(byte * data, uint width, uint height,
  221. uint raster, uint replicated_width, uint replicated_raster)
  222. {
  223. /* The current algorithm is extremely inefficient! */
  224. const byte *orig_row = data + (height - 1) * raster;
  225. byte *tile_row = data + (height - 1) * replicated_raster;
  226. uint y;
  227. if (!(width & 7)) {
  228. uint src_bytes = width >> 3;
  229. uint dest_bytes = replicated_width >> 3;
  230. for (y = height; y-- > 0;
  231. orig_row -= raster, tile_row -= replicated_raster
  232. ) {
  233. uint move = src_bytes;
  234. const byte *from = orig_row;
  235. byte *to = tile_row + dest_bytes - src_bytes;
  236. memmove(to, from, move);
  237. while (to - tile_row >= move) {
  238. from = to;
  239. to -= move;
  240. memmove(to, from, move);
  241. move <<= 1;
  242. }
  243. if (to != tile_row)
  244. memmove(tile_row, to, to - tile_row);
  245. }
  246. } else {
  247. /*
  248. * This algorithm is inefficient, but probably not worth improving.
  249. */
  250. uint bit_count = width & (uint)(-(int)width); /* lowest bit: 1, 2, or 4 */
  251. uint left_mask = (0xff00 >> bit_count) & 0xff;
  252. for (y = height; y-- > 0;
  253. orig_row -= raster, tile_row -= replicated_raster
  254. ) {
  255. uint sx;
  256. for (sx = width; sx > 0;) {
  257. uint bits, dx;
  258. sx -= bit_count;
  259. bits = (orig_row[sx >> 3] << (sx & 7)) & left_mask;
  260. for (dx = sx + replicated_width; dx >= width;) {
  261. byte *dp;
  262. int dbit;
  263. dx -= width;
  264. dbit = dx & 7;
  265. dp = tile_row + (dx >> 3);
  266. *dp = (*dp & ~(left_mask >> dbit)) | (bits >> dbit);
  267. }
  268. }
  269. }
  270. }
  271. }
  272. /* Replicate a bitmap vertically in place. */
  273. void
  274. bits_replicate_vertically(byte * data, uint height, uint raster,
  275. uint replicated_height)
  276. {
  277. byte *dest = data;
  278. uint h = replicated_height;
  279. uint size = raster * height;
  280. while (h > height) {
  281. memcpy(dest + size, dest, size);
  282. dest += size;
  283. h -= height;
  284. }
  285. }
  286. /* Find the bounding box of a bitmap. */
  287. /* Assume bits beyond the width are zero. */
  288. void
  289. bits_bounding_box(const byte * data, uint height, uint raster,
  290. gs_int_rect * pbox)
  291. {
  292. register const ulong *lp;
  293. static const byte first_1[16] = {
  294. 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
  295. };
  296. static const byte last_1[16] = {
  297. 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4
  298. };
  299. /* Count trailing blank rows. */
  300. /* Since the raster is a multiple of sizeof(long), */
  301. /* we don't need to scan by bytes, only by longs. */
  302. lp = (const ulong *)(data + raster * height);
  303. while ((const byte *)lp > data && !lp[-1])
  304. --lp;
  305. if ((const byte *)lp == data) {
  306. pbox->p.x = pbox->q.x = pbox->p.y = pbox->q.y = 0;
  307. return;
  308. }
  309. pbox->q.y = height = ((const byte *)lp - data + raster - 1) / raster;
  310. /* Count leading blank rows. */
  311. lp = (const ulong *)data;
  312. while (!*lp)
  313. ++lp;
  314. {
  315. uint n = ((const byte *)lp - data) / raster;
  316. pbox->p.y = n;
  317. if (n)
  318. height -= n, data += n * raster;
  319. }
  320. /* Find the left and right edges. */
  321. /* We know that the first and last rows are non-blank. */
  322. {
  323. uint raster_longs = raster >> arch_log2_sizeof_long;
  324. uint left = raster_longs - 1, right = 0;
  325. ulong llong = 0, rlong = 0;
  326. const byte *q;
  327. uint h, n;
  328. for (q = data, h = height; h-- > 0; q += raster) { /* Work from the left edge by longs. */
  329. for (lp = (const ulong *)q, n = 0;
  330. n < left && !*lp; lp++, n++
  331. );
  332. if (n < left)
  333. left = n, llong = *lp;
  334. else
  335. llong |= *lp;
  336. /* Work from the right edge by longs. */
  337. for (lp = (const ulong *)(q + raster - sizeof(long)),
  338. n = raster_longs - 1;
  339. n > right && !*lp; lp--, n--
  340. );
  341. if (n > right)
  342. right = n, rlong = *lp;
  343. else
  344. rlong |= *lp;
  345. }
  346. /* Do binary subdivision on edge longs. We assume that */
  347. /* sizeof(long) = 4 or 8. */
  348. #if arch_sizeof_long > 8
  349. Error_longs_are_too_large();
  350. #endif
  351. #if arch_is_big_endian
  352. # define last_bits(n) ((1L << (n)) - 1)
  353. # define shift_out_last(x,n) ((x) >>= (n))
  354. # define right_justify_last(x,n) DO_NOTHING
  355. #else
  356. # define last_bits(n) (-1L << ((arch_sizeof_long * 8) - (n)))
  357. # define shift_out_last(x,n) ((x) <<= (n))
  358. # define right_justify_last(x,n) (x) >>= ((arch_sizeof_long * 8) - (n))
  359. #endif
  360. left <<= arch_log2_sizeof_long + 3;
  361. #if arch_sizeof_long == 8
  362. if (llong & ~last_bits(32))
  363. shift_out_last(llong, 32);
  364. else
  365. left += 32;
  366. #endif
  367. if (llong & ~last_bits(16))
  368. shift_out_last(llong, 16);
  369. else
  370. left += 16;
  371. if (llong & ~last_bits(8))
  372. shift_out_last(llong, 8);
  373. else
  374. left += 8;
  375. right_justify_last(llong, 8);
  376. if (llong & 0xf0)
  377. left += first_1[(byte) llong >> 4];
  378. else
  379. left += first_1[(byte) llong] + 4;
  380. right <<= arch_log2_sizeof_long + 3;
  381. #if arch_sizeof_long == 8
  382. if (!(rlong & last_bits(32)))
  383. shift_out_last(rlong, 32);
  384. else
  385. right += 32;
  386. #endif
  387. if (!(rlong & last_bits(16)))
  388. shift_out_last(rlong, 16);
  389. else
  390. right += 16;
  391. if (!(rlong & last_bits(8)))
  392. shift_out_last(rlong, 8);
  393. else
  394. right += 8;
  395. right_justify_last(rlong, 8);
  396. if (!(rlong & 0xf))
  397. right += last_1[(byte) rlong >> 4];
  398. else
  399. right += last_1[(uint) rlong & 0xf] + 4;
  400. pbox->p.x = left;
  401. pbox->q.x = right;
  402. }
  403. }
  404. /* Extract a plane from a pixmap. */
  405. int
  406. bits_extract_plane(const bits_plane_t *dest /*write*/,
  407. const bits_plane_t *source /*read*/, int shift, int width, int height)
  408. {
  409. int source_depth = source->depth;
  410. int source_bit = source->x * source_depth;
  411. const byte *source_row = source->data.read + (source_bit >> 3);
  412. int dest_depth = dest->depth;
  413. uint plane_mask = (1 << dest_depth) - 1;
  414. int dest_bit = dest->x * dest_depth;
  415. byte *dest_row = dest->data.write + (dest_bit >> 3);
  416. enum {
  417. EXTRACT_SLOW = 0,
  418. EXTRACT_4_TO_1,
  419. EXTRACT_32_TO_8
  420. } loop_case = EXTRACT_SLOW;
  421. int y;
  422. source_bit &= 7;
  423. dest_bit &= 7;
  424. /* Check for the fast CMYK cases. */
  425. if (!(source_bit | dest_bit)) {
  426. switch (source_depth) {
  427. case 4:
  428. loop_case =
  429. (dest_depth == 1 && !(source->raster & 3) &&
  430. !(source->x & 1) ? EXTRACT_4_TO_1 :
  431. EXTRACT_SLOW);
  432. break;
  433. case 32:
  434. if (dest_depth == 8 && !(shift & 7)) {
  435. loop_case = EXTRACT_32_TO_8;
  436. source_row += 3 - (shift >> 3);
  437. }
  438. break;
  439. }
  440. }
  441. for (y = 0; y < height;
  442. ++y, source_row += source->raster, dest_row += dest->raster
  443. ) {
  444. int x;
  445. switch (loop_case) {
  446. case EXTRACT_4_TO_1: {
  447. const byte *source = source_row;
  448. byte *dest = dest_row;
  449. /* Do groups of 8 pixels. */
  450. for (x = width; x >= 8; source += 4, x -= 8) {
  451. bits32 sword =
  452. (*(const bits32 *)source >> shift) & 0x11111111;
  453. *dest++ =
  454. byte_acegbdfh_to_abcdefgh[(
  455. #if arch_is_big_endian
  456. (sword >> 21) | (sword >> 14) | (sword >> 7) | sword
  457. #else
  458. (sword << 3) | (sword >> 6) | (sword >> 15) | (sword >> 24)
  459. #endif
  460. ) & 0xff];
  461. }
  462. if (x) {
  463. /* Do the final 1-7 pixels. */
  464. uint test = 0x10 << shift, store = 0x80;
  465. do {
  466. *dest = (*source & test ? *dest | store : *dest & ~store);
  467. if (test >= 0x10)
  468. test >>= 4;
  469. else
  470. test <<= 4, ++source;
  471. store >>= 1;
  472. } while (--x > 0);
  473. }
  474. break;
  475. }
  476. case EXTRACT_32_TO_8: {
  477. const byte *source = source_row;
  478. byte *dest = dest_row;
  479. for (x = width; x > 0; source += 4, --x)
  480. *dest++ = *source;
  481. break;
  482. }
  483. default: {
  484. sample_load_declare_setup(sptr, sbit, source_row, source_bit,
  485. source_depth);
  486. sample_store_declare_setup(dptr, dbit, dbbyte, dest_row, dest_bit,
  487. dest_depth);
  488. sample_store_preload(dbbyte, dptr, dbit, dest_depth);
  489. for (x = width; x > 0; --x) {
  490. gx_color_index color;
  491. uint pixel;
  492. sample_load_next_any(color, sptr, sbit, source_depth);
  493. pixel = (color >> shift) & plane_mask;
  494. sample_store_next8(pixel, dptr, dbit, dest_depth, dbbyte);
  495. }
  496. sample_store_flush(dptr, dbit, dest_depth, dbbyte);
  497. }
  498. }
  499. }
  500. return 0;
  501. }
  502. /* Expand a plane into a pixmap. */
  503. int
  504. bits_expand_plane(const bits_plane_t *dest /*write*/,
  505. const bits_plane_t *source /*read*/, int shift, int width, int height)
  506. {
  507. /*
  508. * Eventually we will optimize this just like bits_extract_plane.
  509. */
  510. int source_depth = source->depth;
  511. int source_bit = source->x * source_depth;
  512. const byte *source_row = source->data.read + (source_bit >> 3);
  513. int dest_depth = dest->depth;
  514. int dest_bit = dest->x * dest_depth;
  515. byte *dest_row = dest->data.write + (dest_bit >> 3);
  516. enum {
  517. EXPAND_SLOW = 0,
  518. EXPAND_1_TO_4,
  519. EXPAND_8_TO_32
  520. } loop_case = EXPAND_SLOW;
  521. int y;
  522. source_bit &= 7;
  523. /* Check for the fast CMYK cases. */
  524. if (!(source_bit || (dest_bit & 31) || (dest->raster & 3))) {
  525. switch (dest_depth) {
  526. case 4:
  527. if (source_depth == 1)
  528. loop_case = EXPAND_1_TO_4;
  529. break;
  530. case 32:
  531. if (source_depth == 8 && !(shift & 7))
  532. loop_case = EXPAND_8_TO_32;
  533. break;
  534. }
  535. }
  536. dest_bit &= 7;
  537. switch (loop_case) {
  538. case EXPAND_8_TO_32: {
  539. #if arch_is_big_endian
  540. # define word_shift (shift)
  541. #else
  542. int word_shift = 24 - shift;
  543. #endif
  544. for (y = 0; y < height;
  545. ++y, source_row += source->raster, dest_row += dest->raster
  546. ) {
  547. int x;
  548. const byte *source = source_row;
  549. bits32 *dest = (bits32 *)dest_row;
  550. for (x = width; x > 0; --x)
  551. *dest++ = (bits32)(*source++) << word_shift;
  552. }
  553. #undef word_shift
  554. }
  555. break;
  556. case EXPAND_1_TO_4:
  557. default:
  558. for (y = 0; y < height;
  559. ++y, source_row += source->raster, dest_row += dest->raster
  560. ) {
  561. int x;
  562. sample_load_declare_setup(sptr, sbit, source_row, source_bit,
  563. source_depth);
  564. sample_store_declare_setup(dptr, dbit, dbbyte, dest_row, dest_bit,
  565. dest_depth);
  566. sample_store_preload(dbbyte, dptr, dbit, dest_depth);
  567. for (x = width; x > 0; --x) {
  568. uint color;
  569. gx_color_index pixel;
  570. sample_load_next8(color, sptr, sbit, source_depth);
  571. pixel = color << shift;
  572. sample_store_next_any(pixel, dptr, dbit, dest_depth, dbbyte);
  573. }
  574. sample_store_flush(dptr, dbit, dest_depth, dbbyte);
  575. }
  576. break;
  577. }
  578. return 0;
  579. }
  580. /* ---------------- Byte-oriented operations ---------------- */
  581. /* Fill a rectangle of bytes. */
  582. void
  583. bytes_fill_rectangle(byte * dest, uint raster,
  584. byte value, int width_bytes, int height)
  585. {
  586. while (height-- > 0) {
  587. memset(dest, value, width_bytes);
  588. dest += raster;
  589. }
  590. }
  591. /* Copy a rectangle of bytes. */
  592. void
  593. bytes_copy_rectangle(byte * dest, uint dest_raster,
  594. const byte * src, uint src_raster, int width_bytes, int height)
  595. {
  596. while (height-- > 0) {
  597. memcpy(dest, src, width_bytes);
  598. src += src_raster;
  599. dest += dest_raster;
  600. }
  601. }