Leaked source code of windows server 2003
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.

1051 lines
23 KiB

  1. /*
  2. * StretchC.C
  3. *
  4. * StretchBlt for DIBs
  5. *
  6. * C version of stretch.asm: StretchDIB optimised for AVI.
  7. *
  8. * NOTES
  9. * - does not handle mirroring in x or y
  10. * - does not handle pixel translation
  11. * - will not work in place.
  12. *
  13. * AUTHOR
  14. * C version by Geraint Davies
  15. */
  16. #include <windows.h>
  17. #include "drawdibi.h"
  18. #include "stretch.h"
  19. /* Outline:
  20. *
  21. * we select a y-stretching function depending on the ratio (eg 1:N or N:1).
  22. * it copies scanlines from source to destination, duplicating or omitting
  23. * scanlines as necessary to fit the destination. It copies each scanline
  24. * via the X_FUNC function we passed as an argument: this copies one scanline
  25. * duplicating or omitting pixels to fit the destination: we select an X_FUNC
  26. * depending on the bit-depth as well as the x-stretching ratio.
  27. *
  28. * both x and y stretching functions use the following basic model for deciding
  29. * when to insert/omit elements:
  30. *
  31. * delta = <larger extent> -1;
  32. *
  33. * for (number of destination elements) {
  34. *
  35. * copy one element
  36. * advance pointer to larger region
  37. * delta -= <smaller extent>
  38. * if (delta < 0) {
  39. * delta += <larger extent>;
  40. * advance pointer to smaller region
  41. * }
  42. * }
  43. */
  44. /* stretch proportions */
  45. #define STRETCH_1_1 1
  46. #define STRETCH_1_2 2
  47. #define STRETCH_1_4 3
  48. #define STRETCH_1_N 4
  49. #define STRETCH_N_1 5
  50. #define STRETCH_4_1 6
  51. #define STRETCH_2_1 7
  52. /*
  53. * an X_FUNC is a function that copies one scanline, stretching or shrinking it
  54. * to fit a destination scanline. Pick an X_FUNC depending on
  55. * bitdepth and stretch ratio (1:1, 1:2, 1:4, 1:N, N:1, 4:1, 2:1)
  56. *
  57. * the x_fract argument is the delta fraction: it is a representation
  58. * of the smaller extent (whichever that is) as a fraction of the larger,
  59. * and is used when stretching or shrinking to advance the pointer to the
  60. * smaller scanline every (fract) pixels of the larger.
  61. * Thus if we are expanding 1:8, x_fract will be 1/8, we will advance the
  62. * source pointer once every 8 pixels, and thus copy each source pixel to
  63. * 8 dest pixels. Note that if shrinking 8:1, x_fract will still be 1/8
  64. * and we will use it to control advancement of the dest pointer.
  65. * the fraction is multiplied by 65536.
  66. */
  67. typedef void (*X_FUNC) (LPBYTE lpSrc,
  68. LPBYTE lpDst,
  69. int SrcXE,
  70. int DstXE,
  71. int x_fract);
  72. void X_Stretch_1_1_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  73. void X_Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  74. void X_Stretch_1_4_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  75. void X_Stretch_1_N_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  76. void X_Stretch_N_1_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  77. void X_Stretch_1_1_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  78. void X_Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  79. void X_Stretch_1_N_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  80. void X_Stretch_N_1_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  81. void X_Stretch_1_1_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  82. void X_Stretch_1_N_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  83. void X_Stretch_N_1_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  84. /*
  85. * Y_Stretch_* functions copy DstYE scanlines (using
  86. * an X_FUNC to copy each scanline) omitting or duplicating scanlines to
  87. * fit the destination extent. Pick a Y_ depending on the ratio
  88. * (1:N, N:1...)
  89. */
  90. void Y_Stretch_1_N(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  91. int DstYE, int SrcWidth, int DstWidth, int x_fract,
  92. X_FUNC x_func);
  93. void Y_Stretch_N_1(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  94. int DstYE, int SrcWidth, int DstWidth, int x_fract,
  95. X_FUNC x_func);
  96. /*
  97. * special case y-stretch functions for 1:2 in both dimensions for 8 and 16 bits
  98. * takes no X_FUNC arg. Will do entire stretch.
  99. */
  100. void Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  101. int DstYE, int SrcWidth, int DstWidth, int x_fract);
  102. void Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  103. int DstYE, int SrcWidth, int DstWidth, int x_fract);
  104. /* straight copy of one scanline of count bytes */
  105. void X_CopyScanline(LPBYTE lpSrc, LPBYTE lpDst, int count);
  106. /* -------------------------------------------------------------------- */
  107. /*
  108. * StretchFactor
  109. *
  110. * calculate the stretch factor (proportion of source extent to destination
  111. * extent: 1:1, 1:2, 1:4, 1:N, N:1, 4:1,or 2:1) and also the
  112. * delta fraction (see above comment on X_FUNC). This is the ratio of
  113. * the smaller extent to the larger extent, represented as a fraction
  114. * multiplied by 65536.
  115. *
  116. * returns: the stretch factor (stores the delta fraction in *pfract)
  117. */
  118. int
  119. StretchFactor(int SrcE, int DstE, int *pfract)
  120. {
  121. if (SrcE == DstE) {
  122. if (pfract != NULL) {
  123. pfract = 0;
  124. }
  125. return(STRETCH_1_1);
  126. }
  127. if (SrcE > DstE) {
  128. if (pfract != NULL) {
  129. *pfract = ( (DstE << 16) / SrcE) & 0xffff;
  130. }
  131. if (SrcE == (DstE * 2)) {
  132. return(STRETCH_2_1);
  133. } else if (SrcE == (DstE * 4)) {
  134. return(STRETCH_4_1);
  135. } else {
  136. return(STRETCH_N_1);
  137. }
  138. } else {
  139. /* calculate delta fraction based on smallest / largest */
  140. if (pfract != NULL) {
  141. *pfract = ( (SrcE << 16) / DstE) & 0xffff;
  142. }
  143. if (DstE == (SrcE * 2)) {
  144. return(STRETCH_1_2);
  145. } else if (DstE == (SrcE * 4)) {
  146. return(STRETCH_1_4);
  147. } else {
  148. return(STRETCH_1_N);
  149. }
  150. }
  151. }
  152. /* -------------------------------------------------------------------- */
  153. /*
  154. * StretchDIB
  155. *
  156. */
  157. void WINAPI
  158. StretchDIB(
  159. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of destination
  160. LPVOID lpvDst, // --> to destination bits
  161. int DstX, // Destination origin - x coordinate
  162. int DstY, // Destination origin - y coordinate
  163. int DstXE, // x extent of the BLT
  164. int DstYE, // y extent of the BLT
  165. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of source
  166. LPVOID lpvSrc, // --> to source bits
  167. int SrcX, // Source origin - x coordinate
  168. int SrcY, // Source origin - y coordinate
  169. int SrcXE, // x extent of the BLT
  170. int SrcYE // y extent of the BLT
  171. )
  172. {
  173. int nBits;
  174. int SrcWidth, DstWidth;
  175. LPBYTE lpDst = lpvDst, lpSrc = lpvSrc;
  176. int x_fract;
  177. int x_factor;
  178. int y_factor;
  179. X_FUNC xfunc;
  180. /*
  181. * check that bit depths are same and 8, 16 or 24
  182. */
  183. if ((nBits = biDst->biBitCount) != biSrc->biBitCount) {
  184. return;
  185. }
  186. if ( (nBits != 8 ) && (nBits != 16) && (nBits != 24)) {
  187. return;
  188. }
  189. /*
  190. * check that extents are not bad
  191. */
  192. if ( (SrcXE <= 0) || (SrcYE <= 0) || (DstXE <= 0) || (DstYE <= 0)) {
  193. return;
  194. }
  195. /*
  196. * calculate width of one scan line in bytes, rounded up to
  197. * DWORD boundary.
  198. */
  199. SrcWidth = (((biSrc->biWidth * nBits) + 31) & ~31) / 8;
  200. DstWidth = (((biDst->biWidth * nBits) + 31) & ~31) / 8;
  201. /*
  202. * set initial source and dest pointers
  203. */
  204. lpSrc += (SrcY * SrcWidth) + ((SrcX * nBits) / 8);
  205. lpDst += (DstY * DstWidth) + ((DstX * nBits) / 8);
  206. /*
  207. * calculate stretch proportions (1:1, 1:2, 1:N, N:1 etc) and
  208. * also the fractional stretch factor. (we are not interested in
  209. * the y stretch fraction - this is only used in x stretching.
  210. */
  211. y_factor = StretchFactor(SrcYE, DstYE, NULL);
  212. x_factor = StretchFactor(SrcXE, DstXE, &x_fract);
  213. /*
  214. * we have special case routines for 1:2 in both dimensions
  215. * for 8 and 16 bits
  216. */
  217. if ((y_factor == x_factor) && (y_factor == STRETCH_1_2)) {
  218. if (nBits == 8) {
  219. //StartCounting();
  220. Stretch_1_2_8Bits(lpSrc, lpDst, SrcXE, SrcYE,
  221. DstXE, DstYE, SrcWidth, DstWidth,
  222. x_fract);
  223. //EndCounting("8 bit");
  224. return;
  225. } else if (nBits == 16) {
  226. //StartCounting();
  227. Stretch_1_2_16Bits(lpSrc, lpDst, SrcXE, SrcYE,
  228. DstXE, DstYE, SrcWidth, DstWidth,
  229. x_fract);
  230. //EndCounting("16 bit");
  231. return;
  232. }
  233. }
  234. /* pick an X stretch function */
  235. switch(nBits) {
  236. case 8:
  237. switch(x_factor) {
  238. case STRETCH_1_1:
  239. xfunc = X_Stretch_1_1_8Bits;
  240. break;
  241. case STRETCH_1_2:
  242. xfunc = X_Stretch_1_2_8Bits;
  243. break;
  244. case STRETCH_1_4:
  245. xfunc = X_Stretch_1_4_8Bits;
  246. break;
  247. case STRETCH_1_N:
  248. xfunc = X_Stretch_1_N_8Bits;
  249. break;
  250. case STRETCH_N_1:
  251. case STRETCH_4_1:
  252. case STRETCH_2_1:
  253. xfunc = X_Stretch_N_1_8Bits;
  254. break;
  255. }
  256. break;
  257. case 16:
  258. switch(x_factor) {
  259. case STRETCH_1_1:
  260. xfunc = X_Stretch_1_1_16Bits;
  261. break;
  262. case STRETCH_1_2:
  263. xfunc = X_Stretch_1_2_16Bits;
  264. break;
  265. case STRETCH_1_4:
  266. case STRETCH_1_N:
  267. xfunc = X_Stretch_1_N_16Bits;
  268. break;
  269. case STRETCH_N_1:
  270. case STRETCH_4_1:
  271. case STRETCH_2_1:
  272. xfunc = X_Stretch_N_1_16Bits;
  273. break;
  274. }
  275. break;
  276. case 24:
  277. switch(x_factor) {
  278. case STRETCH_1_1:
  279. xfunc = X_Stretch_1_1_24Bits;
  280. break;
  281. case STRETCH_1_2:
  282. case STRETCH_1_4:
  283. case STRETCH_1_N:
  284. xfunc = X_Stretch_1_N_24Bits;
  285. break;
  286. case STRETCH_N_1:
  287. case STRETCH_4_1:
  288. case STRETCH_2_1:
  289. xfunc = X_Stretch_N_1_24Bits;
  290. break;
  291. }
  292. break;
  293. }
  294. /*
  295. * now call appropriate stretching function depending
  296. * on the y stretch factor
  297. */
  298. switch (y_factor) {
  299. case STRETCH_1_1:
  300. case STRETCH_1_2:
  301. case STRETCH_1_4:
  302. case STRETCH_1_N:
  303. Y_Stretch_1_N(lpSrc, lpDst, SrcXE, SrcYE,
  304. DstXE, DstYE, SrcWidth, DstWidth, x_fract, xfunc);
  305. break;
  306. case STRETCH_N_1:
  307. case STRETCH_4_1:
  308. case STRETCH_2_1:
  309. Y_Stretch_N_1(lpSrc, lpDst, SrcXE, SrcYE,
  310. DstXE, DstYE, SrcWidth, DstWidth, x_fract, xfunc);
  311. break;
  312. }
  313. return;
  314. }
  315. /* ---- y stretching -------------------------------------------- */
  316. /*
  317. * call an X_FUNC to copy scanlines from lpSrc to lpDst. Duplicate or
  318. * omit scanlines to stretch SrcYE to DstYE.
  319. */
  320. /*
  321. * Y_Stretch_1_N
  322. *
  323. * write DstYE scanlines based on SrcYE scanlines, DstYE > SrcYE
  324. *
  325. */
  326. void
  327. Y_Stretch_1_N(LPBYTE lpSrc,
  328. LPBYTE lpDst,
  329. int SrcXE,
  330. int SrcYE,
  331. int DstXE,
  332. int DstYE,
  333. int SrcWidth,
  334. int DstWidth,
  335. int x_fract,
  336. X_FUNC x_func)
  337. {
  338. int ydelta;
  339. int i;
  340. LPBYTE lpPrev = NULL;
  341. ydelta = DstYE -1;
  342. for (i = 0; i < DstYE; i++) {
  343. /* have we already stretched this scanline ? */
  344. if (lpPrev == NULL) {
  345. /* no - copy one scanline */
  346. (*x_func)(lpSrc, lpDst, SrcXE, DstXE, x_fract);
  347. lpPrev = lpDst;
  348. } else {
  349. /* yes - this is a duplicate scanline. do
  350. * a straight copy of one that has already
  351. * been stretched/shrunk
  352. */
  353. X_CopyScanline(lpPrev, lpDst, DstWidth);
  354. }
  355. /* advance dest pointer */
  356. lpDst += DstWidth;
  357. /* should we advance source pointer this time ? */
  358. if ( (ydelta -= SrcYE) < 0) {
  359. ydelta += DstYE;
  360. lpSrc += SrcWidth;
  361. lpPrev = NULL;
  362. }
  363. }
  364. }
  365. /*
  366. * Y_Stretch_N_1
  367. *
  368. * write DstYE scanlines based on SrcYE scanlines, DstYE < SrcYE
  369. *
  370. */
  371. void
  372. Y_Stretch_N_1(LPBYTE lpSrc,
  373. LPBYTE lpDst,
  374. int SrcXE,
  375. int SrcYE,
  376. int DstXE,
  377. int DstYE,
  378. int SrcWidth,
  379. int DstWidth,
  380. int x_fract,
  381. X_FUNC x_func)
  382. {
  383. int ydelta;
  384. int i;
  385. ydelta = SrcYE -1;
  386. for (i = 0; i < DstYE; i++) {
  387. /* copy one scanline */
  388. (*x_func)(lpSrc, lpDst, SrcXE, DstXE, x_fract);
  389. /* advance dest pointer */
  390. lpDst += DstWidth;
  391. /* how many times do we advance source pointer this time ? */
  392. do {
  393. lpSrc += SrcWidth;
  394. ydelta -= DstYE;
  395. } while (ydelta >= 0);
  396. ydelta += SrcYE;
  397. }
  398. }
  399. /* ---8-bit X stretching -------------------------------------------------- */
  400. /*
  401. * X_Stretch_1_N_8Bits
  402. *
  403. * copy one scan line, stretching 1:N (DstXE > SrcXE). For 8-bit depth.
  404. */
  405. void
  406. X_Stretch_1_N_8Bits(LPBYTE lpSrc,
  407. LPBYTE lpDst,
  408. int SrcXE,
  409. int DstXE,
  410. int x_fract)
  411. {
  412. int xdelta;
  413. int i;
  414. xdelta = DstXE -1;
  415. for (i = 0; i < DstXE; i++) {
  416. /* copy one byte and advance dest */
  417. *lpDst++ = *lpSrc;
  418. /* should we advance source pointer this time ? */
  419. if ( (xdelta -= SrcXE) < 0) {
  420. xdelta += DstXE;
  421. lpSrc++;
  422. }
  423. }
  424. }
  425. /*
  426. * X_Stretch_N_1_8Bits
  427. *
  428. * copy one scan line, shrinking N:1 (DstXE < SrcXE). For 8-bit depth.
  429. */
  430. void
  431. X_Stretch_N_1_8Bits(LPBYTE lpSrc,
  432. LPBYTE lpDst,
  433. int SrcXE,
  434. int DstXE,
  435. int x_fract)
  436. {
  437. int xdelta;
  438. int i;
  439. xdelta = SrcXE -1;
  440. for (i = 0; i < DstXE; i++) {
  441. /* copy one byte and advance dest */
  442. *lpDst++ = *lpSrc;
  443. /* how many times do we advance source pointer this time ? */
  444. do {
  445. lpSrc++;
  446. xdelta -= DstXE;
  447. } while (xdelta >= 0);
  448. xdelta += SrcXE;
  449. }
  450. }
  451. /*
  452. * copy one scanline of count bytes from lpSrc to lpDst. used by 1:1
  453. * scanline functions for all bit depths
  454. */
  455. void
  456. X_CopyScanline(LPBYTE lpSrc, LPBYTE lpDst, int count)
  457. {
  458. int i;
  459. /*
  460. * if the alignment of lpSrc and lpDst is the same, then
  461. * we can get them aligned and do a faster copy
  462. */
  463. if (((DWORD)(DWORD_PTR) lpSrc & 0x3) == ( (DWORD)(DWORD_PTR) lpDst & 0x3)) {
  464. /* align on WORD boundary */
  465. if ( (DWORD)(DWORD_PTR) lpSrc & 0x1) {
  466. *lpDst++ = *lpSrc++;
  467. count--;
  468. }
  469. /* align on DWORD boundary */
  470. if ((DWORD)(DWORD_PTR) lpSrc & 0x2) {
  471. * ((LPWORD) lpDst) = *((LPWORD) lpSrc);
  472. lpDst += sizeof(WORD);
  473. lpSrc += sizeof(WORD);
  474. count -= sizeof(WORD);
  475. }
  476. /* copy whole DWORDS */
  477. for ( i = (count / 4); i > 0; i--) {
  478. *((LPDWORD) lpDst) = *((LPDWORD) lpSrc);
  479. lpSrc += sizeof(DWORD);
  480. lpDst += sizeof(DWORD);
  481. }
  482. } else {
  483. /* the lpSrc and lpDst pointers are different
  484. * alignment, so leave them unaligned and
  485. * copy all the whole DWORDs
  486. */
  487. for (i = (count / 4); i> 0; i--) {
  488. *( (DWORD UNALIGNED FAR *) lpDst) =
  489. *((DWORD UNALIGNED FAR *) lpSrc);
  490. lpSrc += sizeof(DWORD);
  491. lpDst += sizeof(DWORD);
  492. }
  493. }
  494. /* in either case, copy last (up to 3) bytes. */
  495. for ( i = count % 4; i > 0; i--) {
  496. *lpDst++ = *lpSrc++;
  497. }
  498. }
  499. /*
  500. * X_Stretch_1_1_8Bits
  501. *
  502. * copy a scanline with no change (1:1)
  503. */
  504. void
  505. X_Stretch_1_1_8Bits(LPBYTE lpSrc,
  506. LPBYTE lpDst,
  507. int SrcXE,
  508. int DstXE,
  509. int x_fract)
  510. {
  511. X_CopyScanline(lpSrc, lpDst, DstXE);
  512. }
  513. /*
  514. * X_Stretch_1_2_8Bits
  515. *
  516. * copy a scanline, doubling all the pixels (1:2)
  517. */
  518. void
  519. X_Stretch_1_2_8Bits(LPBYTE lpSrc,
  520. LPBYTE lpDst,
  521. int SrcXE,
  522. int DstXE,
  523. int x_fract)
  524. {
  525. WORD wPix;
  526. int i;
  527. for (i = 0; i < SrcXE; i++) {
  528. /* get a pixel and double it */
  529. wPix = *lpSrc++;
  530. wPix |= (wPix << 8);
  531. * ((WORD UNALIGNED *) lpDst) = wPix;
  532. lpDst += sizeof(WORD);
  533. }
  534. }
  535. /*
  536. * X_Stretch_1_4_8Bits
  537. *
  538. * copy a scanline, quadrupling all the pixels (1:4)
  539. */
  540. void
  541. X_Stretch_1_4_8Bits(LPBYTE lpSrc,
  542. LPBYTE lpDst,
  543. int SrcXE,
  544. int DstXE,
  545. int x_fract)
  546. {
  547. DWORD dwPix;
  548. int i;
  549. for (i = 0; i < SrcXE; i++) {
  550. /* get a pixel and make four copies of it */
  551. dwPix = *lpSrc++;
  552. dwPix |= (dwPix <<8);
  553. dwPix |= (dwPix << 16);
  554. * ((DWORD UNALIGNED *) lpDst) = dwPix;
  555. lpDst += sizeof(DWORD);
  556. }
  557. }
  558. /* -- 16-bit X functions -----------------------------------------------*/
  559. /*
  560. * copy one scan-line of 16 bits with no change (1:1)
  561. */
  562. void
  563. X_Stretch_1_1_16Bits(LPBYTE lpSrc,
  564. LPBYTE lpDst,
  565. int SrcXE,
  566. int DstXE,
  567. int x_fract)
  568. {
  569. X_CopyScanline(lpSrc, lpDst, DstXE * sizeof(WORD));
  570. }
  571. /*
  572. * copy one scanline of 16 bpp duplicating each pixel
  573. */
  574. void
  575. X_Stretch_1_2_16Bits(LPBYTE lpSrc,
  576. LPBYTE lpDst,
  577. int SrcXE,
  578. int DstXE,
  579. int x_fract)
  580. {
  581. DWORD dwPix;
  582. int i;
  583. for (i = 0; i < SrcXE; i++) {
  584. /* get a pixel and double it */
  585. dwPix = * ((WORD *)lpSrc);
  586. dwPix |= (dwPix << 16);
  587. * ((DWORD UNALIGNED *) lpDst) = dwPix;
  588. lpDst += sizeof(DWORD);
  589. lpSrc += sizeof(WORD);
  590. }
  591. }
  592. /*
  593. * copy one scanline of 16 bits, stretching 1:n (dest > source)
  594. */
  595. void
  596. X_Stretch_1_N_16Bits(LPBYTE lpSrc,
  597. LPBYTE lpDst,
  598. int SrcXE,
  599. int DstXE,
  600. int x_fract)
  601. {
  602. int xdelta;
  603. int i;
  604. xdelta = DstXE -1;
  605. for (i = 0; i < DstXE; i++) {
  606. /* copy one pixel and advance dest */
  607. *((WORD *) lpDst) = *((WORD *) lpSrc);
  608. lpDst += sizeof(WORD);
  609. /* should we advance source pointer this time ? */
  610. if ( (xdelta -= SrcXE) < 0) {
  611. xdelta += DstXE;
  612. lpSrc += sizeof(WORD);
  613. }
  614. }
  615. }
  616. /*
  617. * copy one scanline of 16bits, shrinking n:1 (dest < source)
  618. */
  619. void
  620. X_Stretch_N_1_16Bits(LPBYTE lpSrc,
  621. LPBYTE lpDst,
  622. int SrcXE,
  623. int DstXE,
  624. int x_fract)
  625. {
  626. int xdelta;
  627. int i;
  628. xdelta = SrcXE -1;
  629. for (i = 0; i < DstXE; i++) {
  630. /* copy one pixel and advance dest */
  631. *((WORD *) lpDst) = *((WORD *)lpSrc);
  632. lpDst += sizeof(WORD);
  633. /* how many times do we advance source pointer this time ? */
  634. do {
  635. lpSrc += sizeof(WORD);
  636. xdelta -= DstXE;
  637. } while (xdelta >= 0);
  638. xdelta += SrcXE;
  639. }
  640. }
  641. /* 24-bits ---------------------------------------------------------*/
  642. /*
  643. * copy one 24-bpp scanline as is (1:1)
  644. */
  645. void
  646. X_Stretch_1_1_24Bits(LPBYTE lpSrc,
  647. LPBYTE lpDst,
  648. int SrcXE,
  649. int DstXE,
  650. int x_fract)
  651. {
  652. X_CopyScanline(lpSrc, lpDst, DstXE * 3);
  653. }
  654. /*
  655. * copy one 24-bpp scanline stretching 1:n (dest > source)
  656. */
  657. void
  658. X_Stretch_1_N_24Bits(LPBYTE lpSrc,
  659. LPBYTE lpDst,
  660. int SrcXE,
  661. int DstXE,
  662. int x_fract)
  663. {
  664. int xdelta;
  665. int i;
  666. xdelta = DstXE -1;
  667. for (i = 0; i < DstXE; i++) {
  668. /* copy first word of pixel and advance dest */
  669. *((WORD UNALIGNED *) lpDst) = *((WORD UNALIGNED *) lpSrc);
  670. lpDst += sizeof(WORD);
  671. /* copy third byte and advance dest */
  672. *lpDst++ = lpSrc[sizeof(WORD)];
  673. /* should we advance source pointer this time ? */
  674. if ( (xdelta -= SrcXE) < 0) {
  675. xdelta += DstXE;
  676. lpSrc += 3;
  677. }
  678. }
  679. }
  680. /*
  681. * copy one scanline of 24 bits, shrinking n:1 (dest < source)
  682. */
  683. void
  684. X_Stretch_N_1_24Bits(LPBYTE lpSrc,
  685. LPBYTE lpDst,
  686. int SrcXE,
  687. int DstXE,
  688. int x_fract)
  689. {
  690. int xdelta;
  691. int i;
  692. xdelta = SrcXE -1;
  693. for (i = 0; i < DstXE; i++) {
  694. /* copy first word of pixel and advance dest */
  695. *((WORD UNALIGNED *) lpDst) = *((WORD UNALIGNED *) lpSrc);
  696. lpDst += sizeof(WORD);
  697. /* copy third byte and advance dest */
  698. *lpDst++ = lpSrc[sizeof(WORD)];
  699. /* how many times do we advance source pointer this time ? */
  700. do {
  701. lpSrc += 3;
  702. xdelta -= DstXE;
  703. } while (xdelta >= 0);
  704. xdelta += SrcXE;
  705. }
  706. }
  707. /* -- special-case 1:2 -------------------------------------------*/
  708. /*
  709. * stretch 1:2 in both directions, for 8 bits.
  710. *
  711. * An experiment was done on x86 to only write every other line during
  712. * the stretch and when the whole frame was done to use memcpy to fill
  713. * in the gaps. This is slower than doing the stretch in a single pass.
  714. */
  715. void
  716. Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  717. int DstYE, int SrcWidth, int DstWidth, int x_fract)
  718. {
  719. int SrcInc, DstInc;
  720. int i, j;
  721. WORD wPix;
  722. DWORD dwPix4;
  723. /* amount to advance source by at the end of each scan */
  724. SrcInc = SrcWidth - SrcXE;
  725. /* amount to advance dest by at the end of each scan - note
  726. * that we write two scans at once, so advance past the next
  727. * scan line
  728. */
  729. DstInc = (DstWidth * 2) - DstXE;
  730. /*
  731. * we would like to copy the pixels DWORD at a time. this means
  732. * being aligned. if we are currently aligned on a WORD boundary,
  733. * then copy one pixel to get aligned. If we are on a byte
  734. * boundary, we can never get aligned, so use the slower loop.
  735. */
  736. if ( ((DWORD)(DWORD_PTR)lpDst) & 1) {
  737. /*
  738. * dest is byte aligned - so we can never align it
  739. * by writing WORDs - use slow loop.
  740. */
  741. for (i = 0; i < SrcYE; i++) {
  742. for (j = 0; j < SrcXE; j++) {
  743. /* get a pixel and double it */
  744. wPix = *lpSrc++;
  745. wPix |= (wPix<<8);
  746. /* write doubled pixel to this scanline */
  747. *( (WORD UNALIGNED *) lpDst) = wPix;
  748. /* write double pixel to next scanline */
  749. *( (WORD UNALIGNED *) (lpDst + DstWidth)) = wPix;
  750. lpDst += sizeof(WORD);
  751. }
  752. lpSrc += SrcInc;
  753. lpDst += DstInc;
  754. }
  755. return;
  756. }
  757. /*
  758. * this will be the aligned version. align each scan line
  759. */
  760. for ( i = 0; i < SrcYE; i++) {
  761. /* count of pixels remaining */
  762. j = SrcXE;
  763. /* align this scan line */
  764. if (((DWORD)(DWORD_PTR)lpDst) & 2) {
  765. /* word aligned - copy one doubled pixel and we are ok */
  766. wPix = *lpSrc++;
  767. wPix |= (wPix << 8);
  768. *( (WORD *) lpDst) = wPix;
  769. *( (WORD *) (lpDst + DstWidth)) = wPix;
  770. lpDst += sizeof(WORD);
  771. j -= 1;
  772. }
  773. /* now dest is aligned - so loop eating two pixels at a time
  774. * until there is at most one left
  775. */
  776. for ( ; j > 1; j -= 2) {
  777. /* read two pixels and double them */
  778. wPix = * ((WORD UNALIGNED *) lpSrc);
  779. lpSrc += sizeof(WORD);
  780. dwPix4 = (wPix & 0xff) | ((wPix & 0xff) << 8);
  781. dwPix4 |= ((wPix & 0xff00) << 8) | ((wPix & 0xff00) << 16);
  782. *((DWORD *) lpDst) = dwPix4;
  783. *((DWORD *) (lpDst + DstWidth)) = dwPix4;
  784. lpDst += sizeof(DWORD);
  785. }
  786. /* odd byte remaining ? */
  787. if (j > 0) {
  788. /* word aligned - copy one doubled pixel and we are ok */
  789. wPix = *lpSrc++;
  790. wPix |= (wPix << 8);
  791. *( (WORD *) lpDst) = wPix;
  792. *( (WORD *) (lpDst + DstWidth)) = wPix;
  793. lpDst += sizeof(WORD);
  794. j -= 1;
  795. }
  796. lpSrc += SrcInc;
  797. lpDst += DstInc;
  798. }
  799. }
  800. /* ----------------------------------------------------------------*/
  801. /*
  802. * stretch 1:2 in both directions, for 16-bits
  803. */
  804. void
  805. Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  806. int DstYE, int SrcWidth, int DstWidth, int x_fract)
  807. {
  808. int SrcInc, DstInc;
  809. int i, j;
  810. DWORD dwPix;
  811. /* amount to advance source by at the end of each scan */
  812. SrcInc = SrcWidth - (SrcXE * sizeof(WORD));
  813. /* amount to advance dest by at the end of each scan - note
  814. * that we write two scans at once, so advance past the next
  815. * scan line
  816. */
  817. DstInc = (DstWidth * 2) - (DstXE * sizeof(WORD));
  818. for (i = 0; i < SrcYE; i++) {
  819. for (j = 0; j < SrcXE; j++) {
  820. /* get a pixel and double it */
  821. dwPix = *((WORD *)lpSrc);
  822. dwPix |= (dwPix<<16);
  823. lpSrc += sizeof(WORD);
  824. /* write doubled pixel to this scanline */
  825. *( (DWORD UNALIGNED *) lpDst) = dwPix;
  826. /* write double pixel to next scanline */
  827. *( (DWORD UNALIGNED *) (lpDst + DstWidth)) = dwPix;
  828. lpDst += sizeof(DWORD);
  829. }
  830. lpSrc += SrcInc;
  831. lpDst += DstInc;
  832. }
  833. }