/dlls/gdi32/dibdrv/primitives.c

https://github.com/YokoZar/wine · C · 1484 lines · 1275 code · 173 blank · 36 comment · 283 complexity · c516d80f0731933950e0d57b35bade19 MD5 · raw file

  1. /*
  2. * DIB driver primitives.
  3. *
  4. * Copyright 2011 Huw Davies
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include <assert.h>
  21. #include "gdi_private.h"
  22. #include "dibdrv.h"
  23. #include "wine/debug.h"
  24. WINE_DEFAULT_DEBUG_CHANNEL(dib);
  25. static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
  26. {
  27. return (DWORD *)((BYTE*)dib->bits.ptr + y * dib->stride + x * 4);
  28. }
  29. static inline DWORD *get_pixel_ptr_24_dword(const dib_info *dib, int x, int y)
  30. {
  31. return (DWORD *)((BYTE*)dib->bits.ptr + y * dib->stride) + x * 3 / 4;
  32. }
  33. static inline BYTE *get_pixel_ptr_24(const dib_info *dib, int x, int y)
  34. {
  35. return (BYTE*)dib->bits.ptr + y * dib->stride + x * 3;
  36. }
  37. static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
  38. {
  39. return (WORD *)((BYTE*)dib->bits.ptr + y * dib->stride + x * 2);
  40. }
  41. static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
  42. {
  43. return (BYTE*)dib->bits.ptr + y * dib->stride + x;
  44. }
  45. static inline BYTE *get_pixel_ptr_4(const dib_info *dib, int x, int y)
  46. {
  47. return (BYTE*)dib->bits.ptr + y * dib->stride + x / 2;
  48. }
  49. static inline BYTE *get_pixel_ptr_1(const dib_info *dib, int x, int y)
  50. {
  51. return (BYTE*)dib->bits.ptr + y * dib->stride + x / 8;
  52. }
  53. static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
  54. static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
  55. {
  56. *ptr = (*ptr & and) ^ xor;
  57. }
  58. static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
  59. {
  60. *ptr = (*ptr & and) ^ xor;
  61. }
  62. static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
  63. {
  64. *ptr = (*ptr & and) ^ xor;
  65. }
  66. static inline void do_rop_mask_8(BYTE *ptr, BYTE and, BYTE xor, BYTE mask)
  67. {
  68. *ptr = (*ptr & (and | ~mask)) ^ (xor & mask);
  69. }
  70. static inline void do_rop_codes_32(DWORD *dst, DWORD src, struct rop_codes *codes)
  71. {
  72. do_rop_32( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
  73. }
  74. static inline void do_rop_codes_16(WORD *dst, WORD src, struct rop_codes *codes)
  75. {
  76. do_rop_16( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
  77. }
  78. static inline void do_rop_codes_8(BYTE *dst, BYTE src, struct rop_codes *codes)
  79. {
  80. do_rop_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2 );
  81. }
  82. static inline void do_rop_codes_mask_8(BYTE *dst, BYTE src, struct rop_codes *codes, BYTE mask)
  83. {
  84. do_rop_mask_8( dst, (src & codes->a1) ^ codes->a2, (src & codes->x1) ^ codes->x2, mask );
  85. }
  86. static inline void do_rop_codes_line_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
  87. {
  88. for (; len > 0; len--, src++, dst++) do_rop_codes_32( dst, *src, codes );
  89. }
  90. static inline void do_rop_codes_line_rev_32(DWORD *dst, const DWORD *src, struct rop_codes *codes, int len)
  91. {
  92. for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
  93. do_rop_codes_32( dst, *src, codes );
  94. }
  95. static inline void do_rop_codes_line_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
  96. {
  97. for (; len > 0; len--, src++, dst++) do_rop_codes_16( dst, *src, codes );
  98. }
  99. static inline void do_rop_codes_line_rev_16(WORD *dst, const WORD *src, struct rop_codes *codes, int len)
  100. {
  101. for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
  102. do_rop_codes_16( dst, *src, codes );
  103. }
  104. static inline void do_rop_codes_line_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
  105. {
  106. for (; len > 0; len--, src++, dst++) do_rop_codes_8( dst, *src, codes );
  107. }
  108. static inline void do_rop_codes_line_rev_8(BYTE *dst, const BYTE *src, struct rop_codes *codes, int len)
  109. {
  110. for (src += len - 1, dst += len - 1; len > 0; len--, src--, dst--)
  111. do_rop_codes_8( dst, *src, codes );
  112. }
  113. static inline void do_rop_codes_line_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
  114. struct rop_codes *codes, int len)
  115. {
  116. BYTE src_val;
  117. for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x++, src_x++)
  118. {
  119. if (dst_x & 1)
  120. {
  121. if (src_x & 1) src_val = *src++;
  122. else src_val = *src >> 4;
  123. do_rop_codes_mask_8( dst++, src_val, codes, 0x0f );
  124. }
  125. else
  126. {
  127. if (src_x & 1) src_val = *src++ << 4;
  128. else src_val = *src;
  129. do_rop_codes_mask_8( dst, src_val, codes, 0xf0 );
  130. }
  131. }
  132. }
  133. static inline void do_rop_codes_line_rev_4(BYTE *dst, int dst_x, const BYTE *src, int src_x,
  134. struct rop_codes *codes, int len)
  135. {
  136. BYTE src_val;
  137. src_x += len - 1;
  138. dst_x += len - 1;
  139. for (src += src_x / 2, dst += dst_x / 2; len > 0; len--, dst_x--, src_x--)
  140. {
  141. if (dst_x & 1)
  142. {
  143. if (src_x & 1) src_val = *src;
  144. else src_val = *src-- >> 4;
  145. do_rop_codes_mask_8( dst, src_val, codes, 0x0f );
  146. }
  147. else
  148. {
  149. if (src_x & 1) src_val = *src << 4;
  150. else src_val = *src--;
  151. do_rop_codes_mask_8( dst--, src_val, codes, 0xf0 );
  152. }
  153. }
  154. }
  155. static inline void do_rop_codes_line_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
  156. struct rop_codes *codes, int len)
  157. {
  158. BYTE src_val;
  159. for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x++, src_x++)
  160. {
  161. src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
  162. do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
  163. if ((src_x & 7) == 7) src++;
  164. if ((dst_x & 7) == 7) dst++;
  165. }
  166. }
  167. static inline void do_rop_codes_line_rev_1(BYTE *dst, int dst_x, const BYTE *src, int src_x,
  168. struct rop_codes *codes, int len)
  169. {
  170. BYTE src_val;
  171. src_x += len - 1;
  172. dst_x += len - 1;
  173. for (src += src_x / 8, dst += dst_x / 8; len > 0; len--, dst_x--, src_x--)
  174. {
  175. src_val = *src & pixel_masks_1[src_x & 7] ? 0xff : 0;
  176. do_rop_codes_mask_8( dst, src_val, codes, pixel_masks_1[dst_x & 7] );
  177. if ((src_x & 7) == 0) src--;
  178. if ((dst_x & 7) == 0) dst--;
  179. }
  180. }
  181. static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
  182. {
  183. DWORD *ptr, *start;
  184. int x, y, i;
  185. for(i = 0; i < num; i++, rc++)
  186. {
  187. start = get_pixel_ptr_32(dib, rc->left, rc->top);
  188. for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
  189. for(x = rc->left, ptr = start; x < rc->right; x++)
  190. do_rop_32(ptr++, and, xor);
  191. }
  192. }
  193. static void solid_rects_24(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
  194. {
  195. DWORD *ptr, *start;
  196. BYTE *byte_ptr, *byte_start;
  197. int x, y, i;
  198. DWORD and_masks[3], xor_masks[3];
  199. and_masks[0] = ( and & 0x00ffffff) | ((and << 24) & 0xff000000);
  200. and_masks[1] = ((and >> 8) & 0x0000ffff) | ((and << 16) & 0xffff0000);
  201. and_masks[2] = ((and >> 16) & 0x000000ff) | ((and << 8) & 0xffffff00);
  202. xor_masks[0] = ( xor & 0x00ffffff) | ((xor << 24) & 0xff000000);
  203. xor_masks[1] = ((xor >> 8) & 0x0000ffff) | ((xor << 16) & 0xffff0000);
  204. xor_masks[2] = ((xor >> 16) & 0x000000ff) | ((xor << 8) & 0xffffff00);
  205. for(i = 0; i < num; i++, rc++)
  206. {
  207. if(rc->left >= rc->right) continue;
  208. if((rc->left & ~3) == (rc->right & ~3)) /* Special case for lines that start and end in the same DWORD triplet */
  209. {
  210. byte_start = get_pixel_ptr_24(dib, rc->left, rc->top);
  211. for(y = rc->top; y < rc->bottom; y++, byte_start += dib->stride)
  212. {
  213. for(x = rc->left, byte_ptr = byte_start; x < rc->right; x++)
  214. {
  215. do_rop_8(byte_ptr++, and_masks[0] & 0xff, xor_masks[0] & 0xff);
  216. do_rop_8(byte_ptr++, and_masks[1] & 0xff, xor_masks[1] & 0xff);
  217. do_rop_8(byte_ptr++, and_masks[2] & 0xff, xor_masks[2] & 0xff);
  218. }
  219. }
  220. }
  221. else
  222. {
  223. start = get_pixel_ptr_24_dword(dib, rc->left, rc->top);
  224. for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
  225. {
  226. ptr = start;
  227. switch(rc->left & 3)
  228. {
  229. case 1:
  230. do_rop_32(ptr++, and_masks[0] | 0x00ffffff, xor_masks[0] & 0xff000000);
  231. do_rop_32(ptr++, and_masks[1], xor_masks[1]);
  232. do_rop_32(ptr++, and_masks[2], xor_masks[2]);
  233. break;
  234. case 2:
  235. do_rop_32(ptr++, and_masks[1] | 0x0000ffff, xor_masks[1] & 0xffff0000);
  236. do_rop_32(ptr++, and_masks[2], xor_masks[2]);
  237. break;
  238. case 3:
  239. do_rop_32(ptr++, and_masks[2] | 0x000000ff, xor_masks[2] & 0xffffff00);
  240. break;
  241. }
  242. for(x = (rc->left + 3) & ~3; x < (rc->right & ~3); x += 4)
  243. {
  244. do_rop_32(ptr++, and_masks[0], xor_masks[0]);
  245. do_rop_32(ptr++, and_masks[1], xor_masks[1]);
  246. do_rop_32(ptr++, and_masks[2], xor_masks[2]);
  247. }
  248. switch(rc->right & 3)
  249. {
  250. case 1:
  251. do_rop_32(ptr, and_masks[0] | 0xff000000, xor_masks[0] & 0x00ffffff);
  252. break;
  253. case 2:
  254. do_rop_32(ptr++, and_masks[0], xor_masks[0]);
  255. do_rop_32(ptr, and_masks[1] | 0xffff0000, xor_masks[1] & 0x0000ffff);
  256. break;
  257. case 3:
  258. do_rop_32(ptr++, and_masks[0], xor_masks[0]);
  259. do_rop_32(ptr++, and_masks[1], xor_masks[1]);
  260. do_rop_32(ptr, and_masks[2] | 0xffffff00, xor_masks[2] & 0x000000ff);
  261. break;
  262. }
  263. }
  264. }
  265. }
  266. }
  267. static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
  268. {
  269. WORD *ptr, *start;
  270. int x, y, i;
  271. for(i = 0; i < num; i++, rc++)
  272. {
  273. start = get_pixel_ptr_16(dib, rc->left, rc->top);
  274. for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
  275. for(x = rc->left, ptr = start; x < rc->right; x++)
  276. do_rop_16(ptr++, and, xor);
  277. }
  278. }
  279. static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
  280. {
  281. BYTE *ptr, *start;
  282. int x, y, i;
  283. for(i = 0; i < num; i++, rc++)
  284. {
  285. start = get_pixel_ptr_8(dib, rc->left, rc->top);
  286. for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
  287. for(x = rc->left, ptr = start; x < rc->right; x++)
  288. do_rop_8(ptr++, and, xor);
  289. }
  290. }
  291. static void solid_rects_4(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
  292. {
  293. BYTE *ptr, *start;
  294. int x, y, i;
  295. BYTE byte_and = (and & 0xf) | ((and << 4) & 0xf0);
  296. BYTE byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
  297. for(i = 0; i < num; i++, rc++)
  298. {
  299. if(rc->left >= rc->right) continue;
  300. start = get_pixel_ptr_4(dib, rc->left, rc->top);
  301. for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
  302. {
  303. ptr = start;
  304. if(rc->left & 1) /* upper nibble untouched */
  305. do_rop_8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
  306. for(x = (rc->left + 1) & ~1; x < (rc->right & ~1); x += 2)
  307. do_rop_8(ptr++, byte_and, byte_xor);
  308. if(rc->right & 1) /* lower nibble untouched */
  309. do_rop_8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
  310. }
  311. }
  312. }
  313. static void solid_rects_1(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
  314. {
  315. BYTE *ptr, *start;
  316. int x, y, i;
  317. BYTE byte_and = (and & 1) ? 0xff : 0;
  318. BYTE byte_xor = (xor & 1) ? 0xff : 0;
  319. BYTE start_and, start_xor, end_and, end_xor, mask;
  320. static const BYTE masks[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
  321. for(i = 0; i < num; i++, rc++)
  322. {
  323. if(rc->left >= rc->right) continue;
  324. start = get_pixel_ptr_1(dib, rc->left, rc->top);
  325. if((rc->left & ~7) == (rc->right & ~7)) /* Special case for lines that start and end in the same byte */
  326. {
  327. mask = masks[rc->left & 7] & ~masks[rc->right & 7];
  328. start_and = byte_and | ~mask;
  329. start_xor = byte_xor & mask;
  330. for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
  331. {
  332. do_rop_8(start, start_and, start_xor);
  333. }
  334. }
  335. else
  336. {
  337. mask = masks[rc->left & 7];
  338. start_and = byte_and | ~mask;
  339. start_xor = byte_xor & mask;
  340. mask = masks[rc->right & 7];
  341. /* This is inverted wrt to start mask, so end_and/xor assignments reflect this */
  342. end_and = byte_and | mask;
  343. end_xor = byte_xor & ~mask;
  344. for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
  345. {
  346. ptr = start;
  347. if(rc->left & 7)
  348. do_rop_8(ptr++, start_and, start_xor);
  349. for(x = (rc->left + 7) & ~7; x < (rc->right & ~7); x += 8)
  350. do_rop_8(ptr++, byte_and, byte_xor);
  351. if(rc->right & 7)
  352. do_rop_8(ptr, end_and, end_xor);
  353. }
  354. }
  355. }
  356. }
  357. static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
  358. {
  359. return;
  360. }
  361. static inline INT calc_offset(INT edge, INT size, INT origin)
  362. {
  363. INT offset;
  364. if(edge - origin >= 0)
  365. offset = (edge - origin) % size;
  366. else
  367. {
  368. offset = (origin - edge) % size;
  369. if(offset) offset = size - offset;
  370. }
  371. return offset;
  372. }
  373. static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
  374. {
  375. POINT offset;
  376. offset.x = calc_offset(rc->left, brush->width, origin->x);
  377. offset.y = calc_offset(rc->top, brush->height, origin->y);
  378. return offset;
  379. }
  380. static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
  381. const dib_info *brush, void *and_bits, void *xor_bits)
  382. {
  383. DWORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
  384. int x, y, i;
  385. POINT offset;
  386. for(i = 0; i < num; i++, rc++)
  387. {
  388. offset = calc_brush_offset(rc, brush, origin);
  389. start = get_pixel_ptr_32(dib, rc->left, rc->top);
  390. start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
  391. start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
  392. for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
  393. {
  394. and_ptr = start_and + offset.x;
  395. xor_ptr = start_xor + offset.x;
  396. for(x = rc->left, ptr = start; x < rc->right; x++)
  397. {
  398. do_rop_32(ptr++, *and_ptr++, *xor_ptr++);
  399. if(and_ptr == start_and + brush->width)
  400. {
  401. and_ptr = start_and;
  402. xor_ptr = start_xor;
  403. }
  404. }
  405. offset.y++;
  406. if(offset.y == brush->height)
  407. {
  408. start_and = and_bits;
  409. start_xor = xor_bits;
  410. offset.y = 0;
  411. }
  412. else
  413. {
  414. start_and += brush->stride / 4;
  415. start_xor += brush->stride / 4;
  416. }
  417. }
  418. }
  419. }
  420. static void pattern_rects_24(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
  421. const dib_info *brush, void *and_bits, void *xor_bits)
  422. {
  423. BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
  424. int x, y, i;
  425. POINT offset;
  426. for(i = 0; i < num; i++, rc++)
  427. {
  428. offset = calc_brush_offset(rc, brush, origin);
  429. start = get_pixel_ptr_24(dib, rc->left, rc->top);
  430. start_and = (BYTE*)and_bits + offset.y * brush->stride;
  431. start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
  432. for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
  433. {
  434. and_ptr = start_and + offset.x * 3;
  435. xor_ptr = start_xor + offset.x * 3;
  436. for(x = rc->left, ptr = start; x < rc->right; x++)
  437. {
  438. do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
  439. do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
  440. do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
  441. if(and_ptr == start_and + brush->width * 3)
  442. {
  443. and_ptr = start_and;
  444. xor_ptr = start_xor;
  445. }
  446. }
  447. offset.y++;
  448. if(offset.y == brush->height)
  449. {
  450. start_and = and_bits;
  451. start_xor = xor_bits;
  452. offset.y = 0;
  453. }
  454. else
  455. {
  456. start_and += brush->stride;
  457. start_xor += brush->stride;
  458. }
  459. }
  460. }
  461. }
  462. static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
  463. const dib_info *brush, void *and_bits, void *xor_bits)
  464. {
  465. WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
  466. int x, y, i;
  467. POINT offset;
  468. for(i = 0; i < num; i++, rc++)
  469. {
  470. offset = calc_brush_offset(rc, brush, origin);
  471. start = get_pixel_ptr_16(dib, rc->left, rc->top);
  472. start_and = (WORD*)and_bits + offset.y * brush->stride / 2;
  473. start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2;
  474. for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2)
  475. {
  476. and_ptr = start_and + offset.x;
  477. xor_ptr = start_xor + offset.x;
  478. for(x = rc->left, ptr = start; x < rc->right; x++)
  479. {
  480. do_rop_16(ptr++, *and_ptr++, *xor_ptr++);
  481. if(and_ptr == start_and + brush->width)
  482. {
  483. and_ptr = start_and;
  484. xor_ptr = start_xor;
  485. }
  486. }
  487. offset.y++;
  488. if(offset.y == brush->height)
  489. {
  490. start_and = and_bits;
  491. start_xor = xor_bits;
  492. offset.y = 0;
  493. }
  494. else
  495. {
  496. start_and += brush->stride / 2;
  497. start_xor += brush->stride / 2;
  498. }
  499. }
  500. }
  501. }
  502. static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
  503. const dib_info *brush, void *and_bits, void *xor_bits)
  504. {
  505. BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
  506. int x, y, i;
  507. POINT offset;
  508. for(i = 0; i < num; i++, rc++)
  509. {
  510. offset = calc_brush_offset(rc, brush, origin);
  511. start = get_pixel_ptr_8(dib, rc->left, rc->top);
  512. start_and = (BYTE*)and_bits + offset.y * brush->stride;
  513. start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
  514. for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
  515. {
  516. and_ptr = start_and + offset.x;
  517. xor_ptr = start_xor + offset.x;
  518. for(x = rc->left, ptr = start; x < rc->right; x++)
  519. {
  520. do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
  521. if(and_ptr == start_and + brush->width)
  522. {
  523. and_ptr = start_and;
  524. xor_ptr = start_xor;
  525. }
  526. }
  527. offset.y++;
  528. if(offset.y == brush->height)
  529. {
  530. start_and = and_bits;
  531. start_xor = xor_bits;
  532. offset.y = 0;
  533. }
  534. else
  535. {
  536. start_and += brush->stride;
  537. start_xor += brush->stride;
  538. }
  539. }
  540. }
  541. }
  542. static void pattern_rects_4(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
  543. const dib_info *brush, void *and_bits, void *xor_bits)
  544. {
  545. BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
  546. int x, y, i;
  547. POINT offset;
  548. for(i = 0; i < num; i++, rc++)
  549. {
  550. offset = calc_brush_offset(rc, brush, origin);
  551. start = get_pixel_ptr_4(dib, rc->left, rc->top);
  552. start_and = (BYTE*)and_bits + offset.y * brush->stride;
  553. start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
  554. for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
  555. {
  556. INT brush_x = offset.x;
  557. BYTE byte_and, byte_xor;
  558. and_ptr = start_and + brush_x / 2;
  559. xor_ptr = start_xor + brush_x / 2;
  560. for(x = rc->left, ptr = start; x < rc->right; x++)
  561. {
  562. /* FIXME: Two pixels at a time */
  563. if(x & 1) /* lower dst nibble */
  564. {
  565. if(brush_x & 1) /* lower pat nibble */
  566. {
  567. byte_and = *and_ptr++ | 0xf0;
  568. byte_xor = *xor_ptr++ & 0x0f;
  569. }
  570. else /* upper pat nibble */
  571. {
  572. byte_and = (*and_ptr >> 4) | 0xf0;
  573. byte_xor = (*xor_ptr >> 4) & 0x0f;
  574. }
  575. }
  576. else /* upper dst nibble */
  577. {
  578. if(brush_x & 1) /* lower pat nibble */
  579. {
  580. byte_and = (*and_ptr++ << 4) | 0x0f;
  581. byte_xor = (*xor_ptr++ << 4) & 0xf0;
  582. }
  583. else /* upper pat nibble */
  584. {
  585. byte_and = *and_ptr | 0x0f;
  586. byte_xor = *xor_ptr & 0xf0;
  587. }
  588. }
  589. do_rop_8(ptr, byte_and, byte_xor);
  590. if(x & 1) ptr++;
  591. if(++brush_x == brush->width)
  592. {
  593. brush_x = 0;
  594. and_ptr = start_and;
  595. xor_ptr = start_xor;
  596. }
  597. }
  598. offset.y++;
  599. if(offset.y == brush->height)
  600. {
  601. start_and = and_bits;
  602. start_xor = xor_bits;
  603. offset.y = 0;
  604. }
  605. else
  606. {
  607. start_and += brush->stride;
  608. start_xor += brush->stride;
  609. }
  610. }
  611. }
  612. }
  613. static void pattern_rects_1(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
  614. const dib_info *brush, void *and_bits, void *xor_bits)
  615. {
  616. BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
  617. int x, y, i;
  618. POINT offset;
  619. for(i = 0; i < num; i++, rc++)
  620. {
  621. offset = calc_brush_offset(rc, brush, origin);
  622. start = get_pixel_ptr_1(dib, rc->left, rc->top);
  623. start_and = (BYTE*)and_bits + offset.y * brush->stride;
  624. start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
  625. for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
  626. {
  627. INT brush_x = offset.x;
  628. BYTE byte_and, byte_xor;
  629. and_ptr = start_and + brush_x / 8;
  630. xor_ptr = start_xor + brush_x / 8;
  631. for(x = rc->left, ptr = start; x < rc->right; x++)
  632. {
  633. byte_and = (*and_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
  634. byte_and |= ~pixel_masks_1[x % 8];
  635. byte_xor = (*xor_ptr & pixel_masks_1[brush_x % 8]) ? 0xff : 0;
  636. byte_xor &= pixel_masks_1[x % 8];
  637. do_rop_8(ptr, byte_and, byte_xor);
  638. if((x & 7) == 7) ptr++;
  639. if((brush_x & 7) == 7)
  640. {
  641. and_ptr++;
  642. xor_ptr++;
  643. }
  644. if(++brush_x == brush->width)
  645. {
  646. brush_x = 0;
  647. and_ptr = start_and;
  648. xor_ptr = start_xor;
  649. }
  650. }
  651. offset.y++;
  652. if(offset.y == brush->height)
  653. {
  654. start_and = and_bits;
  655. start_xor = xor_bits;
  656. offset.y = 0;
  657. }
  658. else
  659. {
  660. start_and += brush->stride;
  661. start_xor += brush->stride;
  662. }
  663. }
  664. }
  665. }
  666. static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
  667. const dib_info *brush, void *and_bits, void *xor_bits)
  668. {
  669. return;
  670. }
  671. static void copy_rect_32(const dib_info *dst, const RECT *rc,
  672. const dib_info *src, const POINT *origin, int rop2, int overlap)
  673. {
  674. DWORD *dst_start, *src_start;
  675. DWORD and = 0, xor = 0;
  676. struct rop_codes codes;
  677. int y, dst_stride, src_stride;
  678. switch (rop2)
  679. {
  680. case R2_NOP: return;
  681. case R2_NOT: and = ~0u;
  682. /* fall through */
  683. case R2_WHITE: xor = ~0u;
  684. /* fall through */
  685. case R2_BLACK:
  686. dst->funcs->solid_rects( dst, 1, rc, and, xor );
  687. return;
  688. }
  689. if (overlap & OVERLAP_BELOW)
  690. {
  691. dst_start = get_pixel_ptr_32(dst, rc->left, rc->bottom - 1);
  692. src_start = get_pixel_ptr_32(src, origin->x, origin->y + rc->bottom - rc->top - 1);
  693. dst_stride = -dst->stride / 4;
  694. src_stride = -src->stride / 4;
  695. }
  696. else
  697. {
  698. dst_start = get_pixel_ptr_32(dst, rc->left, rc->top);
  699. src_start = get_pixel_ptr_32(src, origin->x, origin->y);
  700. dst_stride = dst->stride / 4;
  701. src_stride = src->stride / 4;
  702. }
  703. if (rop2 == R2_COPYPEN)
  704. {
  705. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  706. memmove( dst_start, src_start, (rc->right - rc->left) * 4 );
  707. return;
  708. }
  709. get_rop_codes( rop2, &codes );
  710. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  711. {
  712. if (overlap & OVERLAP_RIGHT)
  713. do_rop_codes_line_rev_32( dst_start, src_start, &codes, rc->right - rc->left );
  714. else
  715. do_rop_codes_line_32( dst_start, src_start, &codes, rc->right - rc->left );
  716. }
  717. }
  718. static void copy_rect_24(const dib_info *dst, const RECT *rc,
  719. const dib_info *src, const POINT *origin, int rop2, int overlap)
  720. {
  721. BYTE *dst_start, *src_start;
  722. DWORD and = 0, xor = 0;
  723. int y, dst_stride, src_stride;
  724. struct rop_codes codes;
  725. switch (rop2)
  726. {
  727. case R2_NOP: return;
  728. case R2_NOT: and = ~0u;
  729. /* fall through */
  730. case R2_WHITE: xor = ~0u;
  731. /* fall through */
  732. case R2_BLACK:
  733. dst->funcs->solid_rects( dst, 1, rc, and, xor );
  734. return;
  735. }
  736. if (overlap & OVERLAP_BELOW)
  737. {
  738. dst_start = get_pixel_ptr_24(dst, rc->left, rc->bottom - 1);
  739. src_start = get_pixel_ptr_24(src, origin->x, origin->y + rc->bottom - rc->top - 1);
  740. dst_stride = -dst->stride;
  741. src_stride = -src->stride;
  742. }
  743. else
  744. {
  745. dst_start = get_pixel_ptr_24(dst, rc->left, rc->top);
  746. src_start = get_pixel_ptr_24(src, origin->x, origin->y);
  747. dst_stride = dst->stride;
  748. src_stride = src->stride;
  749. }
  750. if (rop2 == R2_COPYPEN)
  751. {
  752. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  753. memmove( dst_start, src_start, (rc->right - rc->left) * 3 );
  754. return;
  755. }
  756. get_rop_codes( rop2, &codes );
  757. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  758. {
  759. if (overlap & OVERLAP_RIGHT)
  760. do_rop_codes_line_rev_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
  761. else
  762. do_rop_codes_line_8( dst_start, src_start, &codes, (rc->right - rc->left) * 3 );
  763. }
  764. }
  765. static void copy_rect_16(const dib_info *dst, const RECT *rc,
  766. const dib_info *src, const POINT *origin, int rop2, int overlap)
  767. {
  768. WORD *dst_start, *src_start;
  769. DWORD and = 0, xor = 0;
  770. int y, dst_stride, src_stride;
  771. struct rop_codes codes;
  772. switch (rop2)
  773. {
  774. case R2_NOP: return;
  775. case R2_NOT: and = ~0u;
  776. /* fall through */
  777. case R2_WHITE: xor = ~0u;
  778. /* fall through */
  779. case R2_BLACK:
  780. dst->funcs->solid_rects( dst, 1, rc, and, xor );
  781. return;
  782. }
  783. if (overlap & OVERLAP_BELOW)
  784. {
  785. dst_start = get_pixel_ptr_16(dst, rc->left, rc->bottom - 1);
  786. src_start = get_pixel_ptr_16(src, origin->x, origin->y + rc->bottom - rc->top - 1);
  787. dst_stride = -dst->stride / 2;
  788. src_stride = -src->stride / 2;
  789. }
  790. else
  791. {
  792. dst_start = get_pixel_ptr_16(dst, rc->left, rc->top);
  793. src_start = get_pixel_ptr_16(src, origin->x, origin->y);
  794. dst_stride = dst->stride / 2;
  795. src_stride = src->stride / 2;
  796. }
  797. if (rop2 == R2_COPYPEN)
  798. {
  799. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  800. memmove( dst_start, src_start, (rc->right - rc->left) * 2 );
  801. return;
  802. }
  803. get_rop_codes( rop2, &codes );
  804. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  805. {
  806. if (overlap & OVERLAP_RIGHT)
  807. do_rop_codes_line_rev_16( dst_start, src_start, &codes, rc->right - rc->left );
  808. else
  809. do_rop_codes_line_16( dst_start, src_start, &codes, rc->right - rc->left );
  810. }
  811. }
  812. static void copy_rect_8(const dib_info *dst, const RECT *rc,
  813. const dib_info *src, const POINT *origin, int rop2, int overlap)
  814. {
  815. BYTE *dst_start, *src_start;
  816. DWORD and = 0, xor = 0;
  817. int y, dst_stride, src_stride;
  818. struct rop_codes codes;
  819. switch (rop2)
  820. {
  821. case R2_NOP: return;
  822. case R2_NOT: and = ~0u;
  823. /* fall through */
  824. case R2_WHITE: xor = ~0u;
  825. /* fall through */
  826. case R2_BLACK:
  827. dst->funcs->solid_rects( dst, 1, rc, and, xor );
  828. return;
  829. }
  830. if (overlap & OVERLAP_BELOW)
  831. {
  832. dst_start = get_pixel_ptr_8(dst, rc->left, rc->bottom - 1);
  833. src_start = get_pixel_ptr_8(src, origin->x, origin->y + rc->bottom - rc->top - 1);
  834. dst_stride = -dst->stride;
  835. src_stride = -src->stride;
  836. }
  837. else
  838. {
  839. dst_start = get_pixel_ptr_8(dst, rc->left, rc->top);
  840. src_start = get_pixel_ptr_8(src, origin->x, origin->y);
  841. dst_stride = dst->stride;
  842. src_stride = src->stride;
  843. }
  844. if (rop2 == R2_COPYPEN)
  845. {
  846. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  847. memmove( dst_start, src_start, (rc->right - rc->left) );
  848. return;
  849. }
  850. get_rop_codes( rop2, &codes );
  851. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  852. {
  853. if (overlap & OVERLAP_RIGHT)
  854. do_rop_codes_line_rev_8( dst_start, src_start, &codes, rc->right - rc->left );
  855. else
  856. do_rop_codes_line_8( dst_start, src_start, &codes, rc->right - rc->left );
  857. }
  858. }
  859. static void copy_rect_4(const dib_info *dst, const RECT *rc,
  860. const dib_info *src, const POINT *origin, int rop2, int overlap)
  861. {
  862. BYTE *dst_start, *src_start;
  863. DWORD and = 0, xor = 0;
  864. int y, dst_stride, src_stride;
  865. struct rop_codes codes;
  866. switch (rop2)
  867. {
  868. case R2_NOP: return;
  869. case R2_NOT: and = ~0u;
  870. /* fall through */
  871. case R2_WHITE: xor = ~0u;
  872. /* fall through */
  873. case R2_BLACK:
  874. dst->funcs->solid_rects( dst, 1, rc, and, xor );
  875. return;
  876. }
  877. if (overlap & OVERLAP_BELOW)
  878. {
  879. dst_start = get_pixel_ptr_4(dst, 0, rc->bottom - 1);
  880. src_start = get_pixel_ptr_4(src, 0, origin->y + rc->bottom - rc->top - 1);
  881. dst_stride = -dst->stride;
  882. src_stride = -src->stride;
  883. }
  884. else
  885. {
  886. dst_start = get_pixel_ptr_4(dst, 0, rc->top);
  887. src_start = get_pixel_ptr_4(src, 0, origin->y);
  888. dst_stride = dst->stride;
  889. src_stride = src->stride;
  890. }
  891. if (rop2 == R2_COPYPEN && (rc->left & 1) == 0 && (origin->x & 1) == 0 && (rc->right & 1) == 0)
  892. {
  893. dst_start += rc->left / 2;
  894. src_start += origin->x / 2;
  895. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  896. memmove( dst_start, src_start, (rc->right - rc->left) / 2 );
  897. return;
  898. }
  899. get_rop_codes( rop2, &codes );
  900. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  901. {
  902. if (overlap & OVERLAP_RIGHT)
  903. do_rop_codes_line_rev_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
  904. else
  905. do_rop_codes_line_4( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
  906. }
  907. }
  908. static void copy_rect_1(const dib_info *dst, const RECT *rc,
  909. const dib_info *src, const POINT *origin, int rop2, int overlap)
  910. {
  911. BYTE *dst_start, *src_start;
  912. DWORD and = 0, xor = 0;
  913. int y, dst_stride, src_stride;
  914. struct rop_codes codes;
  915. switch (rop2)
  916. {
  917. case R2_NOP: return;
  918. case R2_NOT: and = ~0u;
  919. /* fall through */
  920. case R2_WHITE: xor = ~0u;
  921. /* fall through */
  922. case R2_BLACK:
  923. dst->funcs->solid_rects( dst, 1, rc, and, xor );
  924. return;
  925. }
  926. if (overlap & OVERLAP_BELOW)
  927. {
  928. dst_start = get_pixel_ptr_1(dst, 0, rc->bottom - 1);
  929. src_start = get_pixel_ptr_1(src, 0, origin->y + rc->bottom - rc->top - 1);
  930. dst_stride = -dst->stride;
  931. src_stride = -src->stride;
  932. }
  933. else
  934. {
  935. dst_start = get_pixel_ptr_1(dst, 0, rc->top);
  936. src_start = get_pixel_ptr_1(src, 0, origin->y);
  937. dst_stride = dst->stride;
  938. src_stride = src->stride;
  939. }
  940. if (rop2 == R2_COPYPEN && (rc->left & 7) == 0 && (origin->x & 7) == 0 && (rc->right & 7) == 0)
  941. {
  942. dst_start += rc->left / 8;
  943. src_start += origin->x / 8;
  944. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  945. memmove( dst_start, src_start, (rc->right - rc->left) / 8 );
  946. return;
  947. }
  948. get_rop_codes( rop2, &codes );
  949. for (y = rc->top; y < rc->bottom; y++, dst_start += dst_stride, src_start += src_stride)
  950. {
  951. if (overlap & OVERLAP_RIGHT)
  952. do_rop_codes_line_rev_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
  953. else
  954. do_rop_codes_line_1( dst_start, rc->left, src_start, origin->x, &codes, rc->right - rc->left );
  955. }
  956. }
  957. static void copy_rect_null(const dib_info *dst, const RECT *rc,
  958. const dib_info *src, const POINT *origin, int rop2, int overlap)
  959. {
  960. return;
  961. }
  962. static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
  963. {
  964. return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
  965. }
  966. static inline DWORD put_field(DWORD field, int shift, int len)
  967. {
  968. shift = shift - (8 - len);
  969. if (len <= 8)
  970. field &= (((1 << len) - 1) << (8 - len));
  971. if (shift < 0)
  972. field >>= -shift;
  973. else
  974. field <<= shift;
  975. return field;
  976. }
  977. static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour)
  978. {
  979. DWORD r,g,b;
  980. r = GetRValue(colour);
  981. g = GetGValue(colour);
  982. b = GetBValue(colour);
  983. return put_field(r, dib->red_shift, dib->red_len) |
  984. put_field(g, dib->green_shift, dib->green_len) |
  985. put_field(b, dib->blue_shift, dib->blue_len);
  986. }
  987. static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
  988. {
  989. return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
  990. }
  991. static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
  992. {
  993. int i, best_index = 0;
  994. RGBQUAD rgb;
  995. DWORD diff, best_diff = 0xffffffff;
  996. rgb.rgbRed = GetRValue(color);
  997. rgb.rgbGreen = GetGValue(color);
  998. rgb.rgbBlue = GetBValue(color);
  999. /* special case for conversion to 1-bpp without a color table:
  1000. * we get a 1-entry table containing the background color
  1001. */
  1002. if (dib->bit_count == 1 && dib->color_table_size == 1)
  1003. return (rgb.rgbRed == dib->color_table[0].rgbRed &&
  1004. rgb.rgbGreen == dib->color_table[0].rgbGreen &&
  1005. rgb.rgbBlue == dib->color_table[0].rgbBlue);
  1006. for(i = 0; i < dib->color_table_size; i++)
  1007. {
  1008. RGBQUAD *cur = dib->color_table + i;
  1009. diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
  1010. + (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
  1011. + (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
  1012. if(diff == 0)
  1013. {
  1014. best_index = i;
  1015. break;
  1016. }
  1017. if(diff < best_diff)
  1018. {
  1019. best_diff = diff;
  1020. best_index = i;
  1021. }
  1022. }
  1023. return best_index;
  1024. }
  1025. static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
  1026. {
  1027. return 0;
  1028. }
  1029. static inline BOOL bit_fields_match(const dib_info *d1, const dib_info *d2)
  1030. {
  1031. assert( d1->bit_count > 8 && d1->bit_count == d2->bit_count );
  1032. return d1->red_mask == d2->red_mask &&
  1033. d1->green_mask == d2->green_mask &&
  1034. d1->blue_mask == d2->blue_mask;
  1035. }
  1036. static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
  1037. {
  1038. DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
  1039. int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
  1040. switch(src->bit_count)
  1041. {
  1042. case 32:
  1043. {
  1044. DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
  1045. if(src->funcs == &funcs_8888)
  1046. {
  1047. if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
  1048. memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
  1049. else
  1050. {
  1051. for(y = src_rect->top; y < src_rect->bottom; y++)
  1052. {
  1053. memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
  1054. if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
  1055. dst_start += dst->stride / 4;
  1056. src_start += src->stride / 4;
  1057. }
  1058. }
  1059. }
  1060. else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8)
  1061. {
  1062. for(y = src_rect->top; y < src_rect->bottom; y++)
  1063. {
  1064. dst_pixel = dst_start;
  1065. src_pixel = src_start;
  1066. for(x = src_rect->left; x < src_rect->right; x++)
  1067. {
  1068. src_val = *src_pixel++;
  1069. *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << 16) |
  1070. (((src_val >> src->green_shift) & 0xff) << 8) |
  1071. ((src_val >> src->blue_shift) & 0xff);
  1072. }
  1073. if(pad_size) memset(dst_pixel, 0, pad_size);
  1074. dst_start += dst->stride / 4;
  1075. src_start += src->stride / 4;
  1076. }
  1077. }
  1078. else
  1079. {
  1080. FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask);
  1081. return FALSE;
  1082. }
  1083. break;
  1084. }
  1085. case 24:
  1086. {
  1087. BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
  1088. for(y = src_rect->top; y < src_rect->bottom; y++)
  1089. {
  1090. dst_pixel = dst_start;
  1091. src_pixel = src_start;
  1092. for(x = src_rect->left; x < src_rect->right; x++)
  1093. {
  1094. RGBQUAD rgb;
  1095. rgb.rgbBlue = *src_pixel++;
  1096. rgb.rgbGreen = *src_pixel++;
  1097. rgb.rgbRed = *src_pixel++;
  1098. *dst_pixel++ = ((rgb.rgbRed << 16) & 0xff0000) | ((rgb.rgbGreen << 8) & 0x00ff00) | (rgb.rgbBlue & 0x0000ff);
  1099. }
  1100. if(pad_size) memset(dst_pixel, 0, pad_size);
  1101. dst_start += dst->stride / 4;
  1102. src_start += src->stride;
  1103. }
  1104. break;
  1105. }
  1106. case 16:
  1107. {
  1108. WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
  1109. if(src->funcs == &funcs_555)
  1110. {
  1111. for(y = src_rect->top; y < src_rect->bottom; y++)
  1112. {
  1113. dst_pixel = dst_start;
  1114. src_pixel = src_start;
  1115. for(x = src_rect->left; x < src_rect->right; x++)
  1116. {
  1117. src_val = *src_pixel++;
  1118. *dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
  1119. ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
  1120. ((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
  1121. }
  1122. if(pad_size) memset(dst_pixel, 0, pad_size);
  1123. dst_start += dst->stride / 4;
  1124. src_start += src->stride / 2;
  1125. }
  1126. }
  1127. else if(src->red_len == 5 && src->green_len == 5 && src->blue_len == 5)
  1128. {
  1129. for(y = src_rect->top; y < src_rect->bottom; y++)
  1130. {
  1131. dst_pixel = dst_start;
  1132. src_pixel = src_start;
  1133. for(x = src_rect->left; x < src_rect->right; x++)
  1134. {
  1135. src_val = *src_pixel++;
  1136. *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
  1137. (((src_val >> src->red_shift) << 14) & 0x070000) |
  1138. (((src_val >> src->green_shift) << 11) & 0x00f800) |
  1139. (((src_val >> src->green_shift) << 6) & 0x000700) |
  1140. (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
  1141. (((src_val >> src->blue_shift) >> 2) & 0x000007);
  1142. }
  1143. if(pad_size) memset(dst_pixel, 0, pad_size);
  1144. dst_start += dst->stride / 4;
  1145. src_start += src->stride / 2;
  1146. }
  1147. }
  1148. else if(src->red_len == 5 && src->green_len == 6 && src->blue_len == 5)
  1149. {
  1150. for(y = src_rect->top; y < src_rect->bottom; y++)
  1151. {
  1152. dst_pixel = dst_start;
  1153. src_pixel = src_start;
  1154. for(x = src_rect->left; x < src_rect->right; x++)
  1155. {
  1156. src_val = *src_pixel++;
  1157. *dst_pixel++ = (((src_val >> src->red_shift) << 19) & 0xf80000) |
  1158. (((src_val >> src->red_shift) << 14) & 0x070000) |
  1159. (((src_val >> src->green_shift) << 10) & 0x00fc00) |
  1160. (((src_val >> src->green_shift) << 4) & 0x000300) |
  1161. (((src_val >> src->blue_shift) << 3) & 0x0000f8) |
  1162. (((src_val >> src->blue_shift) >> 2) & 0x000007);
  1163. }
  1164. if(pad_size) memset(dst_pixel, 0, pad_size);
  1165. dst_start += dst->stride / 4;
  1166. src_start += src->stride / 2;
  1167. }
  1168. }
  1169. else
  1170. {
  1171. FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask);
  1172. return FALSE;
  1173. }
  1174. break;
  1175. }
  1176. case 8:
  1177. {
  1178. BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
  1179. for(y = src_rect->top; y < src_rect->bottom; y++)
  1180. {
  1181. dst_pixel = dst_start;
  1182. src_pixel = src_start;
  1183. for(x = src_rect->left; x < src_rect->right; x++)
  1184. {
  1185. RGBQUAD rgb;
  1186. src_val = *src_pixel++;
  1187. if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
  1188. rgb = src->color_table[src_val];
  1189. *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
  1190. }
  1191. if(pad_size) memset(dst_pixel, 0, pad_size);
  1192. dst_start += dst->stride / 4;
  1193. src_start += src->stride;
  1194. }
  1195. break;
  1196. }
  1197. case 4:
  1198. {
  1199. BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
  1200. for(y = src_rect->top; y < src_rect->bottom; y++)
  1201. {
  1202. dst_pixel = dst_start;
  1203. src_pixel = src_start;
  1204. for(x = src_rect->left; x < src_rect->right; x++)
  1205. {
  1206. RGBQUAD rgb;
  1207. if(x & 1)
  1208. src_val = *src_pixel++ & 0xf;
  1209. else
  1210. src_val = (*src_pixel >> 4) & 0xf;
  1211. if(src_val >= src->color_table_size) src_val = src->color_table_size - 1;
  1212. rgb = src->color_table[src_val];
  1213. *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
  1214. }
  1215. if(pad_size) memset(dst_pixel, 0, pad_size);
  1216. dst_start += dst->stride / 4;
  1217. src_start += src->stride;
  1218. }
  1219. break;
  1220. }
  1221. case 1:
  1222. {
  1223. BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top), *src_pixel;
  1224. for(y = src_rect->top; y < src_rect->bottom; y++)
  1225. {
  1226. dst_pixel = dst_start;
  1227. src_pixel = src_start;
  1228. for(x = src_rect->left; x < src_rect->right; x++)
  1229. {
  1230. RGBQUAD rgb;
  1231. src_val = (*src_pixel & pixel_masks_1[x % 8]) ? 1 : 0;
  1232. if((x % 8) == 7) src_pixel++;
  1233. rgb = src->color_table[src_val];
  1234. *dst_pixel++ = rgb.rgbRed << 16 | rgb.rgbGreen << 8 | rgb.rgbBlue;
  1235. }
  1236. if(pad_size) memset(dst_pixel, 0, pad_size);
  1237. dst_start += dst->stride / 4;
  1238. src_start += src->stride;
  1239. }
  1240. break;
  1241. }
  1242. default:
  1243. FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
  1244. return FALSE;
  1245. }
  1246. return TRUE;
  1247. }
  1248. static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
  1249. {
  1250. DWORD *dst_start = get_pixel_ptr_32(dst, 0, 0), *dst_pixel, src_val;
  1251. int x, y, pad_size = (dst->width - (src_rect->right - src_rect->left)) * 4;
  1252. switch(src->bit_count)
  1253. {
  1254. case 32:
  1255. {
  1256. DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
  1257. if(src->funcs == &funcs_8888)
  1258. {
  1259. for(y = src_rect->top; y < src_rect->bottom; y++)
  1260. {
  1261. dst_pixel = dst_start;
  1262. src_pixel = src_start;
  1263. for(x = src_rect->left; x < src_rect->right; x++)
  1264. {
  1265. src_val = *src_pixel++;
  1266. *dst_pixel++ = put_field((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
  1267. put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
  1268. put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
  1269. }
  1270. if(pad_size) memset(dst_pixel, 0, pad_size);
  1271. dst_start += dst->stride / 4;
  1272. src_start += src->stride / 4;
  1273. }
  1274. }
  1275. else if(bit_fields_match(src, dst))
  1276. {
  1277. if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
  1278. memcpy(dst_start, src_start, (src_rect->bottom - src_rect->top) * src->stride);
  1279. else
  1280. {
  1281. for(y = src_rect->top; y < src_rect->bottom; y++)
  1282. {
  1283. memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
  1284. if(pad_size) memset(dst_start + (src_rect->right - src_rect->left), 0, pad_size);
  1285. dst_start += dst->stride / 4;
  1286. src_start += src->stride / 4;
  1287. }
  1288. }
  1289. }
  1290. else if(src->red_len == 8 && src->green_len == 8 && src->blue_len == 8 &&
  1291. dst->red_len == 8 && dst->green_len == 8 && dst->blue_len == 8)
  1292. {
  1293. for(y = src_rect->top; y < src_rect->bottom; y++)
  1294. {
  1295. dst_pixel = dst_start;
  1296. src_pixel = src_start;
  1297. for(x = src_rect->left; x < src_rect->right; x++)
  1298. {
  1299. src_val = *src_pixel++;
  1300. *dst_pixel++ = (((src_val >> src->red_shift) & 0xff) << dst->red_shift) |
  1301. (((src_val >> src->green_shift) & 0xff) << dst->green_shift) |
  1302. (((src_val >> src->blue_shift) & 0xff) << dst->blue_shift);
  1303. }
  1304. if(pad_size) memset(dst_pixel, 0, pad_size);
  1305. dst_start += dst->stride / 4;
  1306. src_start += src->stride / 4;
  1307. }
  1308. }
  1309. else
  1310. {
  1311. FIXME("Unsupported conversion: 32 (%08x, %08x, %08x) -> 32 (%08x, %08x, %08x)\n",