/******************************Module*Header*******************************\ * Module Name: rotate.cxx * * Internal DDAs for EngPlgBlt * * Created: 06-Aug-1992 15:35:02 * Author: Donald Sidoroff [donalds] * * Copyright (c) 1992-1999 Microsoft Corporation \**************************************************************************/ #include "precomp.hxx" #include "rotate.hxx" #ifdef DBG_PLGBLT extern BOOL gflPlgBlt; #endif int aiPlgConst[][6] = { { 1, 0, 0, 0, 1, 0 }, { 0, 1, 0, 1, 0, 0 }, { -1, 0, 1, 0, 1, 0 }, { 0, 1, 0, -1, 0, 1 }, { 0, -1, 1, 1, 0, 0 }, { 1, 0, 0, 0, -1, 1 }, { 0, -1, 1, -1, 0, 1 }, { -1, 0, 1, 0, -1, 1 } }; int aiPlgSort[][4] = { { 0, 1, 2, 3 }, { 0, 2, 1, 3 }, { 1, 0, 3, 2 }, { 1, 3, 0, 2 }, { 2, 0, 3, 1 }, { 2, 3, 0, 1 }, { 3, 1, 2, 0 }, { 3, 2, 1, 0 } }; static VOID ROT_DIV( DIV_T *pdt, LONG lNum, LONG lDen) { pdt->lQuo = lNum / lDen; pdt->lRem = lNum % lDen; if (pdt->lRem < 0) { pdt->lQuo -= 1; pdt->lRem += lDen; } #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) DbgPrint("%ld / %ld = %ld R %ld\n", lNum, lDen, pdt->lQuo, pdt->lRem); #endif } static VOID QDIV( DIV_T *pdt, LONGLONG *peqNum, LONG lDen) { ULONGLONG liQuo; ULONG ul; BOOL bSigned; bSigned = *peqNum < 0; if (bSigned) { liQuo = (ULONGLONG) (- (LONGLONG) *peqNum); } else liQuo = *peqNum; pdt->lQuo = DIVREM(liQuo, lDen, &ul); if (bSigned) { pdt->lQuo = - pdt->lQuo; if (ul == 0) pdt->lRem = 0; else { pdt->lQuo -= 1; pdt->lRem = lDen - ((LONG) ul); } } else { pdt->lRem = (LONG) ul; } #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) DbgPrint("%ld,%ld / %ld = %ld R %ld\n", peqNum->HighPart, peqNum->LowPart, lDen, pdt->lQuo, pdt->lRem); #endif } /******************************Public*Routine******************************\ * VOID vInitPlgDDA(pdda, pptl) * * Initialize the DDA * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ BOOL bInitPlgDDA( PLGDDA *pdda, RECTL *prclScan, RECTL *prcl, POINTFIX *pptfx) { POINTFIX aptfx[4]; RECTL rclScan; RECTL rcl; aptfx[0] = pptfx[0]; aptfx[1] = pptfx[1]; aptfx[2] = pptfx[2]; aptfx[3].x = aptfx[1].x + aptfx[2].x - aptfx[0].x; aptfx[3].y = aptfx[1].y + aptfx[2].y - aptfx[0].y; // If the source surface does not have a 0,0 origin, deal with it here. if ((prcl->left != 0) || (prcl->top != 0)) { rclScan.left = prclScan->left - prcl->left; rclScan.top = prclScan->top - prcl->top; rclScan.right = prclScan->right - prcl->left; rclScan.bottom = prclScan->bottom - prcl->top; prclScan = &rclScan; rcl.left = 0; rcl.top = 0; rcl.right = prcl->right - prcl->left; rcl.bottom = prcl->bottom - prcl->top; prcl = &rcl; } #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) { DbgPrint("prclScan = [(%ld,%ld) (%ld,%ld)]\n", prclScan->left, prclScan->top, prclScan->right, prclScan->bottom); DbgPrint("prcl = [(%ld,%ld) (%ld,%ld)]\n", prcl->left, prcl->top, prcl->right, prcl->bottom); DbgPrint("aptfx[0] = (%ld,%ld)\n", aptfx[0].x, aptfx[0].y); DbgPrint("aptfx[1] = (%ld,%ld)\n", aptfx[1].x, aptfx[1].y); DbgPrint("aptfx[2] = (%ld,%ld)\n", aptfx[2].x, aptfx[2].y); DbgPrint("aptfx[3] = (%ld,%ld)\n", aptfx[3].x, aptfx[3].y); } #endif int iTop = (aptfx[1].y > aptfx[0].y) == (aptfx[1].y > aptfx[3].y); int iCase; if (aptfx[iTop].y > aptfx[iTop ^ 3].y) iTop ^= 3; switch (iTop) { case 0: if (aptfx[1].y < aptfx[2].y) iCase = 0; else if (aptfx[1].y > aptfx[2].y) iCase = 1; else if (aptfx[1].x < aptfx[2].x) iCase = 0; else iCase = 1; break; case 1: if (aptfx[0].y < aptfx[3].y) iCase = 2; else if (aptfx[0].y > aptfx[3].y) iCase = 3; else if (aptfx[0].x < aptfx[3].x) iCase = 2; else iCase = 3; break; case 2: if (aptfx[0].y < aptfx[3].y) iCase = 4; else if (aptfx[0].y > aptfx[3].y) iCase = 5; else if (aptfx[0].x < aptfx[3].x) iCase = 4; else iCase = 5; break; case 3: if (aptfx[1].y < aptfx[2].y) iCase = 6; else if (aptfx[1].y > aptfx[2].y) iCase = 7; else if (aptfx[1].x < aptfx[2].x) iCase = 6; else iCase = 7; break; } #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) DbgPrint("iTop = %ld, iCase = %ld\n", iTop, iCase); #endif LONG DELTA_1; LONG DELTA_2; switch (iCase) { case 0: case 2: case 5: case 7: DELTA_1 = prcl->right - prcl->left; DELTA_2 = prcl->bottom - prcl->top; break; case 1: case 3: case 4: case 6: DELTA_1 = prcl->bottom - prcl->top; DELTA_2 = prcl->right - prcl->left; break; } LONG ci1 = aiPlgConst[iCase][0]; LONG cj1 = aiPlgConst[iCase][1]; LONG c1 = aiPlgConst[iCase][2]; LONG ci2 = aiPlgConst[iCase][3]; LONG cj2 = aiPlgConst[iCase][4]; LONG c2 = aiPlgConst[iCase][5]; #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) DbgPrint("Global constants: %ld %ld %ld %ld %ld %ld %ld %ld\n", DELTA_1, DELTA_2, ci1, cj1, c1, ci2, cj2, c2); #endif LONG V1 = ci1 * prclScan->left + cj1 * prclScan->top + c1 * (DELTA_1 - 1); LONG V2 = ci2 * prclScan->left + cj2 * prclScan->top + c2 * (DELTA_2 - 1); #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) DbgPrint("V1 = %ld, V2 = %ld\n", V1, V2); #endif LONG I0 = aptfx[aiPlgSort[iCase][0]].x; LONG J0 = aptfx[aiPlgSort[iCase][0]].y; LONG I1 = aptfx[aiPlgSort[iCase][1]].x; LONG J1 = aptfx[aiPlgSort[iCase][1]].y; LONG I2 = aptfx[aiPlgSort[iCase][2]].x; LONG J2 = aptfx[aiPlgSort[iCase][2]].y; LONG I3 = aptfx[aiPlgSort[iCase][3]].x; LONG J3 = aptfx[aiPlgSort[iCase][3]].y; I1 -= I0; I2 -= I0; I3 -= I0; J1 -= J0; J2 -= J0; J3 -= J0; #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) { DbgPrint("I0, I1, I2, I3 = %8ld %8ld %8ld %8ld\n", I0, I1, I2, I3); DbgPrint("J0, J1, J2, J3 = %8ld %8ld %8ld %8ld\n", J0, J1, J2, J3); } #endif LONG X1 = DELTA_2 * I1; LONG Y1 = DELTA_2 * J1; LONG X2 = DELTA_1 * I2; LONG Y2 = DELTA_1 * J2; // avoid divide by 0's. In some way shape or form, all divides are based on // these two values. Note that by checking Y2, DELTA_1 is also validated. We // can't just validate Y1 as well because it is special cased below to be 0. // Also beware of overflows given large numbers where multipications can // potentially shift off all set bits leaving you with a zero value. In the case // where we just lose bits but don't end up with all zeros we will have // undefined but non-exception (divide by zero) behavior if ((Y2 == 0) || (DELTA_2 == 0)) return(FALSE); LONG T = DELTA_1 * DELTA_2; LONGLONG N = Int32x32To64(T, (J0 + 16)); LONGLONG eqTmp = Int32x32To64(V1, Y1); N += eqTmp; eqTmp = Int32x32To64(V2, Y2); N += eqTmp; N -= 1; // LONG N = T * (J0 + 16) + V1 * Y1 + V2 * Y2 - 1; #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) { DbgPrint("X1 = %ld, Y1 = %ld, X2 = %ld, Y2 = %ld\n", X1, Y1, X2, Y2); DbgPrint("T = %ld, N = %ld,%ld\n", T, N.HighPart, N.LowPart); } #endif T *= 16; // overflow check: avoid divide by 0's if ( T == 0 ) return(FALSE); DDA_STEP dp1; DDA_STEP dp2; ROT_DIV(&dp1.dt, Y1, T); dp1.lDen = T; ROT_DIV(&dp2.dt, Y2, T); dp2.lDen = T; QDIV(&pdda->ds.dt0, &N, T); pdda->ds.dt1 = pdda->ds.dt0; DDA(&pdda->ds.dt1, &dp1) pdda->ds.dt2 = pdda->ds.dt0; DDA(&pdda->ds.dt2, &dp2) pdda->ds.dt3 = pdda->ds.dt2; DDA(&pdda->ds.dt3, &dp1) #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) { DbgPrint("N0, N1, N2, N3 = %8ld %8ld %8ld %8ld\n", pdda->ds.dt0.lQuo, pdda->ds.dt1.lQuo, pdda->ds.dt2.lQuo, pdda->ds.dt3.lQuo); DbgPrint("R0, R1, R2, R3 = %8ld %8ld %8ld %8ld\n", pdda->ds.dt0.lRem, pdda->ds.dt1.lRem, pdda->ds.dt2.lRem, pdda->ds.dt3.lRem); } #endif ROT_DIV(&pdda->dp0_i.dt, ci1 * Y1 + ci2 * Y2, T); pdda->dp0_i.lDen = T; pdda->dp1_i = pdda->dp0_i; pdda->dp2_i = pdda->dp0_i; pdda->dp3_i = pdda->dp0_i; ROT_DIV(&pdda->dp0_j.dt, cj1 * Y1 + cj2 * Y2, T); pdda->dp0_j.lDen = T; pdda->dp1_j = pdda->dp0_j; pdda->dp2_j = pdda->dp0_j; pdda->dp3_j = pdda->dp0_j; LONGLONG Q = Int32x32To64(I1, J2); eqTmp = Int32x32To64(J1, I2); Q -= eqTmp; // LONG Q = I1 * J2 - J1 * I2; #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_INIT) DbgPrint("Q = %ld,%ld\n", Q.HighPart, Q.LowPart); #endif DIV_T dt1; DIV_T dt2; //overflow check: avoid divide by 0's if ((16 * DELTA_1) == 0 || (16 * DELTA_2) == 0) return(FALSE); ROT_DIV(&dt1, ci1 * J1, 16 * DELTA_1); ROT_DIV(&dt2, ci2 * J2, 16 * DELTA_2); LONG dn_i = dt1.lQuo + dt2.lQuo; ROT_DIV(&dt1, cj1 * J1, 16 * DELTA_1); ROT_DIV(&dt2, cj2 * J2, 16 * DELTA_2); LONG dn_j = dt1.lQuo + dt2.lQuo; if (Y1 == 0) { pdda->dp01.dt.lQuo = 0; pdda->dp01.dt.lRem = 0; pdda->dp01.lDen = 0; pdda->dp01_i.dt.lQuo = 0; pdda->dp01_i.dt.lRem = 0; pdda->dp01_i.lDen = 0; pdda->dp01_j.dt.lQuo = 0; pdda->dp01_j.dt.lRem = 0; pdda->dp01_j.lDen = 0; pdda->ds.dt01.lQuo = 0; pdda->ds.dt01.lRem = 0; pdda->ds.dt23.lQuo = 0; pdda->ds.dt23.lRem = 0; pdda->dpP01.dt.lQuo = 0; pdda->dpP01.dt.lRem = 0; pdda->dpP01.lDen = 0; } else { N= Int32x32To64(X1, 16 * pdda->ds.dt0.lQuo - J0); eqTmp= Int32x32To64(Y1, (I0 + 16)); N += eqTmp; eqTmp= Int32x32To64(V2, I1 * J2); N -= eqTmp; eqTmp= Int32x32To64(V2, I2 * J1); N += eqTmp; N -= 1; // N = X1 * (16 * pdda->ds.dt0.lQuo - J0) + Y1 * (I0 + 16) - V2 * Q - 1; pdda->dp01.lDen = 16 * Y1; pdda->dp01_i.lDen = pdda->dp01.lDen; pdda->dp01_j.lDen = pdda->dp01.lDen; // overflow check: avoid divide by 0's. if (pdda->dp01.lDen == 0) return(FALSE); QDIV(&pdda->ds.dt01, &N, pdda->dp01.lDen); eqTmp= Int32x32To64(16 * X1, pdda->ds.dt2.lQuo - pdda->ds.dt0.lQuo); eqTmp -= Q; N += eqTmp; // N += 16 * X1 * (pdda->ds.dt2.lQuo - pdda->ds.dt0.lQuo) - Q; QDIV(&pdda->ds.dt23, &N, pdda->dp01.lDen); ROT_DIV(&pdda->dp01.dt, 16 * X1, pdda->dp01.lDen); N= Int32x32To64(ci2 * I1,J2); eqTmp= Int32x32To64(ci2 * I2, J1); N -= eqTmp; // Q * ci2 eqTmp= Int32x32To64(16 * dn_i, X1); eqTmp -= N; QDIV(&pdda->dp01_i.dt, &eqTmp, pdda->dp01_i.lDen); N= Int32x32To64(cj2 * I1,J2); eqTmp= Int32x32To64(cj2 * I2, J1); N -= eqTmp; // Q * cj2 eqTmp= Int32x32To64(16 * dn_j, X1); eqTmp -= N; QDIV(&pdda->dp01_j.dt, &eqTmp, pdda->dp01_j.lDen); // ROT_DIV(&pdda->dp01_i.dt, 16 * X1 * dn_i - ci2 * Q, pdda->dp01_i.lDen); // ROT_DIV(&pdda->dp01_j.dt, 16 * X1 * dn_j - cj2 * Q, pdda->dp01_j.lDen); // overflow check: avoid divide by 0's // 16*Y1 was already checked above computing pdda->dp01.lDen ROT_DIV(&pdda->dpP01.dt, 16 * X1, 16 * Y1); pdda->dpP01.lDen = 16 * Y1; } N= Int32x32To64(X2, 16 * pdda->ds.dt0.lQuo - J0); eqTmp= Int32x32To64(Y2, I0 + 16); N += eqTmp; eqTmp= Int32x32To64(V1, I1 * J2); N += eqTmp; eqTmp= Int32x32To64(V1, I2 * J1); N -= eqTmp; N -= 1; // N = Y1 * (16 * pdda->ds.dt0.lQuo - J0) + Y2 * (I0 + 16) + V1 * Q - 1; pdda->dp02.lDen = 16 * Y2; pdda->dp02_i.lDen = pdda->dp02.lDen; pdda->dp02_j.lDen = pdda->dp02.lDen; // overflow check: avoid divide by 0's. if (pdda->dp02.lDen == 0) return(FALSE); QDIV(&pdda->ds.dt02, &N, pdda->dp02.lDen); eqTmp= Int32x32To64(16 * X2, pdda->ds.dt1.lQuo - pdda->ds.dt0.lQuo); eqTmp += Q; N += eqTmp; // N += 16 * Y1 * (pdda->ds.dt1.lQuo - pdda->ds.dt0.lQuo) + Q; QDIV(&pdda->ds.dt13, &N, pdda->dp02.lDen); ROT_DIV(&pdda->dp02.dt, 16 * X2, pdda->dp02.lDen); N= Int32x32To64(ci1 * I1,J2); eqTmp= Int32x32To64(ci1 * I2, J1); N -= eqTmp; // Q * ci1 eqTmp= Int32x32To64(16 * dn_i, X2); eqTmp += N; QDIV(&pdda->dp02_i.dt, &eqTmp, pdda->dp02_i.lDen); N= Int32x32To64(cj1 * I1,J2); eqTmp= Int32x32To64(cj1 * I2, J1); N -= eqTmp; // Q * cj1 eqTmp= Int32x32To64(16 * dn_j, X2); eqTmp += N; QDIV(&pdda->dp02_j.dt, &eqTmp, pdda->dp02_j.lDen); // DIV(&pdda->dp02_i.dt, 16 * X2 * dn_i + ci1 * Q, pdda->dp02_i.lDen); // DIV(&pdda->dp02_j.dt, 16 * X2 * dn_j + cj1 * Q, pdda->dp02_j.lDen); pdda->dp13 = pdda->dp02; pdda->dp13_i = pdda->dp02_i; pdda->dp13_j = pdda->dp02_j; pdda->dp23 = pdda->dp01; pdda->dp23_i = pdda->dp01_i; pdda->dp23_j = pdda->dp01_j; // overflow check: avoid divide by 0's // 16*Y2 was already checked above computing pdda->dp02.lDen ROT_DIV(&pdda->dpP02.dt, 16 * X2, 16 * Y2); pdda->dpP02.lDen = 16 * Y2; return(TRUE); } /******************************Public*Routine******************************\ * LONG lSizeDDA(pdda) * * Return the space needed to run the DDA for a scan * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ LONG lSizeDDA(PLGDDA *pdda) { LONG dt[4]; LONG max, min, i; // Bug #336058: // Prior to this fix, this function assumed that dt0 contains the // top-most vertex and dt3 contains the bottom-most vertex in the // parallelogram. However, under some calls to EngPlgBlt this appears // to not be true (the bug includes a test program that can // demonstrate this). That caused the allocated buffer to not be large // enough which resulted in an AV (i.e. when doing the run from dt1 // to dt2). The fix is to find the smallest and largest vertices (with // respect to y-values) and allocate enough space for a run from the // smallest to the largest. dt[0] = pdda->ds.dt0.lQuo; dt[1] = pdda->ds.dt1.lQuo; dt[2] = pdda->ds.dt2.lQuo; dt[3] = pdda->ds.dt3.lQuo; max = min = dt[0]; for (i=1; i<4; i++) { if (min > dt[i]) { min = dt[i]; } if (max < dt[i]) { max = dt[i]; } } //LONG lTmp = pdda->ds.dt3.lQuo - pdda->ds.dt0.lQuo; LONG lTmp = max-min; if (lTmp == 0) lTmp = 1; return((lTmp + 4) * sizeof(CNTPOS) + sizeof(ULONG)); } /******************************Public*Routine******************************\ * VOID vAdvXDDA(pdda) * * Advance the DDA in X. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vAdvXDDA(PLGDDA *pdda) { pdda->dsX.dt0.lQuo += pdda->dp0_i.dt.lQuo; pdda->dsX.dt0.lRem += pdda->dp0_i.dt.lRem; if (pdda->dsX.dt0.lRem >= pdda->dp0_i.lDen) { pdda->dsX.dt0.lRem -= pdda->dp0_i.lDen; pdda->dsX.dt0.lQuo++; DDA(&pdda->dsX.dt01, &pdda->dpP01); DDA(&pdda->dsX.dt02, &pdda->dpP02); } pdda->dsX.dt1.lQuo += pdda->dp1_i.dt.lQuo; pdda->dsX.dt1.lRem += pdda->dp1_i.dt.lRem; if (pdda->dsX.dt1.lRem >= pdda->dp1_i.lDen) { pdda->dsX.dt1.lRem -= pdda->dp1_i.lDen; pdda->dsX.dt1.lQuo++; DDA(&pdda->dsX.dt13, &pdda->dpP02); } pdda->dsX.dt2.lQuo += pdda->dp2_i.dt.lQuo; pdda->dsX.dt2.lRem += pdda->dp2_i.dt.lRem; if (pdda->dsX.dt2.lRem >= pdda->dp2_i.lDen) { pdda->dsX.dt2.lRem -= pdda->dp2_i.lDen; pdda->dsX.dt2.lQuo++; DDA(&pdda->dsX.dt23, &pdda->dpP01); } DDA(&pdda->dsX.dt3, &pdda->dp3_i); DDA(&pdda->dsX.dt01, &pdda->dp01_i); DDA(&pdda->dsX.dt02, &pdda->dp02_i); DDA(&pdda->dsX.dt13, &pdda->dp13_i); DDA(&pdda->dsX.dt23, &pdda->dp23_i); } /******************************Public*Routine******************************\ * VOID vAdvYDDA(pdda) * * Advance the DDA in Y. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vAdvYDDA(PLGDDA *pdda) { pdda->ds.dt0.lQuo += pdda->dp0_j.dt.lQuo; pdda->ds.dt0.lRem += pdda->dp0_j.dt.lRem; if (pdda->ds.dt0.lRem >= pdda->dp0_j.lDen) { pdda->ds.dt0.lRem -= pdda->dp0_j.lDen; pdda->ds.dt0.lQuo++; DDA(&pdda->ds.dt01, &pdda->dpP01); DDA(&pdda->ds.dt02, &pdda->dpP02); } pdda->ds.dt1.lQuo += pdda->dp1_j.dt.lQuo; pdda->ds.dt1.lRem += pdda->dp1_j.dt.lRem; if (pdda->ds.dt1.lRem >= pdda->dp1_j.lDen) { pdda->ds.dt1.lRem -= pdda->dp1_j.lDen; pdda->ds.dt1.lQuo++; DDA(&pdda->ds.dt13, &pdda->dpP02); } pdda->ds.dt2.lQuo += pdda->dp2_j.dt.lQuo; pdda->ds.dt2.lRem += pdda->dp2_j.dt.lRem; if (pdda->ds.dt2.lRem >= pdda->dp2_j.lDen) { pdda->ds.dt2.lRem -= pdda->dp2_j.lDen; pdda->ds.dt2.lQuo++; DDA(&pdda->ds.dt23, &pdda->dpP01); } DDA(&pdda->ds.dt3, &pdda->dp3_j); DDA(&pdda->ds.dt01, &pdda->dp01_j); DDA(&pdda->ds.dt02, &pdda->dp02_j); DDA(&pdda->ds.dt13, &pdda->dp13_j); DDA(&pdda->ds.dt23, &pdda->dp23_j); } /******************************Public*Routine******************************\ * PLGRUN *prunPumpDDA(pdda, prun) * * 'Pump' out the target point run for the source point. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ PLGRUN *prunPumpDDA( PLGDDA *pdda, PLGRUN *prun) { DIV_T dt01 = pdda->dsX.dt01; DIV_T dt02 = pdda->dsX.dt02; DIV_T dt13 = pdda->dsX.dt13; DIV_T dt23 = pdda->dsX.dt23; CNTPOS *pcp; LONG n = pdda->dsX.dt0.lQuo; prun->cpY.iPos = n; pcp = &prun->cpX[0]; #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_PUMP) { DbgPrint("Pumping pel\n"); DbgPrint("N0 = %ld\n", n); DbgPrint("N1 = %ld\n", pdda->dsX.dt1.lQuo); DbgPrint("N2 = %ld\n", pdda->dsX.dt2.lQuo); DbgPrint("N3 = %ld\n", pdda->dsX.dt3.lQuo); DbgPrint("DDA 01 = %ld, %ld\n", dt01.lQuo, dt01.lRem); DbgPrint("DDA 02 = %ld, %ld\n", dt02.lQuo, dt02.lRem); DbgPrint("DDA 13 = %ld, %ld\n", dt13.lQuo, dt13.lRem); DbgPrint("DDA 23 = %ld, %ld\n", dt23.lQuo, dt23.lRem); DbgPrint("Step 01 = %ld, %ld, %ld\n", pdda->dp01.dt.lQuo, pdda->dp01.dt.lRem, pdda->dp01.lDen); DbgPrint("Step 02 = %ld, %ld, %ld\n", pdda->dp02.dt.lQuo, pdda->dp02.dt.lRem, pdda->dp02.lDen); DbgPrint("Step 13 = %ld, %ld, %ld\n", pdda->dp13.dt.lQuo, pdda->dp13.dt.lRem, pdda->dp13.lDen); DbgPrint("Step 23 = %ld, %ld, %ld\n", pdda->dp23.dt.lQuo, pdda->dp23.dt.lRem, pdda->dp23.lDen); } #endif while(n < pdda->dsX.dt1.lQuo) { #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_PUMP) DbgPrint("@ Y = %ld, X0 = %ld, X1 = %ld\n", n, dt01.lQuo, dt02.lQuo); #endif if (dt01.lQuo < dt02.lQuo) { pcp->iPos = dt01.lQuo; pcp->cCnt = dt02.lQuo - dt01.lQuo; } else { pcp->iPos = dt02.lQuo; pcp->cCnt = dt01.lQuo - dt02.lQuo; } prun->cpY.cCnt++; DDA(&dt01, &pdda->dp01); DDA(&dt02, &pdda->dp02); pcp++; n++; } #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_PUMP) DbgPrint("Switching LHS to 13\n"); #endif while(n < pdda->dsX.dt2.lQuo) { #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_PUMP) DbgPrint("@ Y = %ld, X0 = %ld, X1 = %ld\n", n, dt13.lQuo, dt02.lQuo); #endif if (dt13.lQuo < dt02.lQuo) { pcp->iPos = dt13.lQuo; pcp->cCnt = dt02.lQuo - dt13.lQuo; } else { pcp->iPos = dt02.lQuo; pcp->cCnt = dt13.lQuo - dt02.lQuo; } prun->cpY.cCnt++; DDA(&dt13, &pdda->dp13); DDA(&dt02, &pdda->dp02); pcp++; n++; } #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_PUMP) DbgPrint("Switching RHS to 23\n"); #endif while(n < pdda->dsX.dt3.lQuo) { #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_PUMP) DbgPrint("@ Y = %ld, X0 = %ld, X1 = %ld\n", n, dt13.lQuo, dt23.lQuo); #endif if (dt13.lQuo < dt23.lQuo) { pcp->iPos = dt13.lQuo; pcp->cCnt = dt23.lQuo - dt13.lQuo; } else { pcp->iPos = dt23.lQuo; pcp->cCnt = dt13.lQuo - dt23.lQuo; } prun->cpY.cCnt++; DDA(&dt13, &pdda->dp13); DDA(&dt23, &pdda->dp23); pcp++; n++; } #ifdef DBG_PLGBLT if (gflPlgBlt & PLGBLT_SHOW_PUMP) DbgPrint("Done.\n"); #endif prun->cpY.cCnt = n - prun->cpY.iPos; // Always put at least one X pair in the list. This handles the BLACKONWHITE // and WHITEONBLACK compression. Notice that the size of the X run is zero. if ((pdda->bOverwrite) && (prun->cpY.cCnt == 0)) { if (dt13.lQuo < dt02.lQuo) { pcp->iPos = dt13.lQuo; pcp->cCnt = dt02.lQuo - dt13.lQuo; } else { pcp->iPos = dt02.lQuo; pcp->cCnt = dt13.lQuo - dt02.lQuo; } prun->cpY.cCnt = 1; pcp++; } return((PLGRUN *) pcp); } static ULONG gaulMaskMono[] = { 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001, 0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100, 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000, 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000 }; static ULONG gaulMaskQuad[] = { 0x000000F0, 0x0000000F, 0x0000F000, 0x00000F00, 0x00F00000, 0x000F0000, 0xF0000000, 0x0F000000 }; static ULONG gaulShftQuad[] = { 0x00000004, 0x00000000, 0x0000000C, 0x00000008, 0x00000014, 0x00000010, 0x0000001C, 0x00000018 }; /******************************Public*Routine******************************\ * PLGRUN *prunPlgRead1(prun, pjSrc, pjMask, pxlo, xLeft, xRght, xMask) * * Read the source, mask it, xlate colors and produce a run list * for a row of a 1BPP surface. * * History: * 12-Feb-1993 -by- Donald Sidoroff [donalds] * Fixed a LOT of bugs in monochrome sources * * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ PLGRUN *prunPlgRead1( PLGDDA *pdda, PLGRUN *prun, BYTE *pjSrc, BYTE *pjMask, XLATEOBJ *pxlo, LONG xLeft, LONG xRght, LONG xMask) { ULONG *pulMsk; ULONG *pulSrc; ULONG ulMsk; ULONG ulSrc; ULONG iBlack; ULONG iWhite; LONG cLeft; LONG iLeft; LONG iMask; cLeft = xLeft >> 5; // Index of leftmost DWORD iLeft = xLeft & 31; // Bits used in leftmost DWORD pulSrc = ((DWORD *) pjSrc) + cLeft; // Adjust base address ulSrc = *pulSrc; // To prevent derefences of the XLATE, do it upfront. We can easily do // this on monochrome bitmaps. if (pxlo == NULL) { iBlack = 0; iWhite = 1; } else { iBlack = pxlo->pulXlate[0]; iWhite = pxlo->pulXlate[1]; } if (pjMask == (BYTE *) NULL) { if (xLeft < xRght) { while (TRUE) { if (ulSrc & gaulMaskMono[iLeft]) prun->iColor = iWhite; else prun->iColor = iBlack; prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); xLeft++; iLeft++; if (xLeft >= xRght) break; if (iLeft & 32) { pulSrc++; ulSrc = *pulSrc; iLeft = 0; } } } return(prun); } // Compute initial state of mask pulMsk = ((DWORD *) pjMask) + (xMask >> 5); iMask = xMask & 31; ulMsk = *pulMsk; if (xLeft < xRght) { while (TRUE) { if (ulMsk & gaulMaskMono[iMask]) { if (ulSrc & gaulMaskMono[iLeft]) prun->iColor = iWhite; else prun->iColor = iBlack; prun = prunPumpDDA(pdda, prun); } vAdvXDDA(pdda); xLeft++; iLeft++; iMask++; if (xLeft >= xRght) break; if (iLeft & 32) { pulSrc++; ulSrc = *pulSrc; iLeft = 0; } if (iMask & 32) { pulMsk++; ulMsk = *pulMsk; iMask = 0; } } } return(prun); } /******************************Public*Routine******************************\ * PLGRUN *prunPlgRead4(prun, pjSrc, pjMask, pxlo, xLeft, xRght, xMask) * * Read the source, mask it, xlate colors and produce a run list * for a row of a 4BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ PLGRUN *prunPlgRead4( PLGDDA *pdda, PLGRUN *prun, BYTE *pjSrc, BYTE *pjMask, XLATEOBJ *pxlo, LONG xLeft, LONG xRght, LONG xMask) { ULONG *pulMsk; ULONG *pulSrc; ULONG ulMsk; ULONG ulSrc; ULONG iColor; LONG cLeft; LONG iLeft; LONG iMask; cLeft = xLeft >> 3; // Index of leftmost DWORD iLeft = xLeft & 7; // Bits used in leftmost DWORD pulSrc = ((DWORD *) pjSrc) + cLeft; // Adjust base address ulSrc = *pulSrc; if (pjMask == (BYTE *) NULL) { if (xLeft < xRght) { while (TRUE) { iColor = (ulSrc & gaulMaskQuad[iLeft]) >> gaulShftQuad[iLeft]; if (pxlo == NULL) prun->iColor = iColor; else prun->iColor = pxlo->pulXlate[iColor]; prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); xLeft++; iLeft++; if (xLeft >= xRght) break; if (iLeft & 8) { pulSrc++; ulSrc = *pulSrc; iLeft = 0; } } } return(prun); } // Compute initial state of mask pulMsk = ((DWORD *) pjMask) + (xMask >> 5); iMask = xMask & 31; ulMsk = *pulMsk; if (xLeft < xRght) { while (TRUE) { if (ulMsk & gaulMaskMono[iMask]) { iColor = (ulSrc & gaulMaskQuad[iLeft]) >> gaulShftQuad[iLeft]; if (pxlo == NULL) prun->iColor = iColor; else prun->iColor = pxlo->pulXlate[iColor]; prun = prunPumpDDA(pdda, prun); } vAdvXDDA(pdda); xLeft++; iLeft++; iMask++; if (xLeft >= xRght) break; if (iLeft & 8) { pulSrc++; ulSrc = *pulSrc; iLeft = 0; } if (iMask & 32) { pulMsk++; ulMsk = *pulMsk; iMask = 0; } } } return(prun); } /******************************Public*Routine******************************\ * PLGRUN *prunPlgRead8(prun, pjSrc, pjMask, pxlo, xLeft, xRght, xMask) * * Read the source, mask it, xlate colors and produce a run list * for a row of a 8BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ PLGRUN *prunPlgRead8( PLGDDA *pdda, PLGRUN *prun, BYTE *pjSrc, BYTE *pjMask, XLATEOBJ *pxlo, LONG xLeft, LONG xRght, LONG xMask) { ULONG *pulMsk; ULONG ulMsk; ULONG iColor; LONG iMask; pjSrc += xLeft; if (pjMask == (BYTE *) NULL) { if (pxlo == NULL) while (xLeft != xRght) { prun->iColor = *pjSrc; prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); pjSrc++; xLeft++; } else while (xLeft != xRght) { prun->iColor = pxlo->pulXlate[*pjSrc]; prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); pjSrc++; xLeft++; } return(prun); } // Compute initial state of mask pulMsk = ((DWORD *) pjMask) + (xMask >> 5); iMask = xMask & 31; ulMsk = *pulMsk; while (xLeft != xRght) { if (ulMsk & gaulMaskMono[iMask]) { iColor = *pjSrc; if (pxlo == NULL) prun->iColor = iColor; else prun->iColor = pxlo->pulXlate[iColor]; prun = prunPumpDDA(pdda, prun); } vAdvXDDA(pdda); pjSrc++; xLeft++; iMask++; if (iMask & 32) { pulMsk++; ulMsk = *pulMsk; iMask = 0; } } return(prun); } /******************************Public*Routine******************************\ * PLGRUN *prunPlgRead16(prun, pjSrc, pjMask, pxlo, xLeft, xRght, xMask) * * Read the source, mask it, xlate colors and produce a run list * for a row of a 16BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ PLGRUN *prunPlgRead16( PLGDDA *pdda, PLGRUN *prun, BYTE *pjSrc, BYTE *pjMask, XLATEOBJ *pxlo, LONG xLeft, LONG xRght, LONG xMask) { WORD *pwSrc = (WORD *) pjSrc; ULONG *pulMsk; ULONG ulMsk; ULONG iColor; LONG iMask; pwSrc += xLeft; if (pjMask == (BYTE *) NULL) { if (pxlo == NULL) while (xLeft != xRght) { prun->iColor = *pwSrc; prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); pwSrc++; xLeft++; } else while (xLeft != xRght) { prun->iColor = ((XLATE *) pxlo)->ulTranslate((ULONG) *pwSrc); prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); pwSrc++; xLeft++; } return(prun); } // Compute initial state of mask pulMsk = ((DWORD *) pjMask) + (xMask >> 5); iMask = xMask & 31; ulMsk = *pulMsk; while (xLeft != xRght) { if (ulMsk & gaulMaskMono[iMask]) { iColor = *pwSrc; if (pxlo == NULL) prun->iColor = iColor; else prun->iColor = ((XLATE *) pxlo)->ulTranslate(iColor); prun = prunPumpDDA(pdda, prun); } vAdvXDDA(pdda); pwSrc++; xLeft++; iMask++; if (iMask & 32) { pulMsk++; ulMsk = *pulMsk; iMask = 0; } } return(prun); } /******************************Public*Routine******************************\ * PLGRUN *prunPlgRead24(prun, pjSrc, pjMask, pxlo, xLeft, xRght, xMask) * * Read the source, mask it, xlate colors and produce a run list * for a row of a 24BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ PLGRUN *prunPlgRead24( PLGDDA *pdda, PLGRUN *prun, BYTE *pjSrc, BYTE *pjMask, XLATEOBJ *pxlo, LONG xLeft, LONG xRght, LONG xMask) { RGBTRIPLE *prgbSrc = (RGBTRIPLE *) pjSrc; ULONG *pulMsk; ULONG ulMsk; ULONG iColor = 0; LONG iMask; prgbSrc += xLeft; if (pjMask == (BYTE *) NULL) { if (pxlo == NULL) while (xLeft != xRght) { *((RGBTRIPLE *) &iColor) = *prgbSrc; prun->iColor = iColor; prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); prgbSrc++; xLeft++; } else while (xLeft != xRght) { *((RGBTRIPLE *) &iColor) = *prgbSrc; prun->iColor = ((XLATE *) pxlo)->ulTranslate(iColor); prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); prgbSrc++; xLeft++; } return(prun); } // Compute initial state of mask pulMsk = ((DWORD *) pjMask) + (xMask >> 5); iMask = xMask & 31; ulMsk = *pulMsk; while (xLeft != xRght) { if (ulMsk & gaulMaskMono[iMask]) { *((RGBTRIPLE *) &iColor) = *prgbSrc; if (pxlo == NULL) prun->iColor = iColor; else prun->iColor = ((XLATE *) pxlo)->ulTranslate(iColor); prun = prunPumpDDA(pdda, prun); } vAdvXDDA(pdda); prgbSrc++; xLeft++; iMask++; if (iMask & 32) { pulMsk++; ulMsk = *pulMsk; iMask = 0; } } return(prun); } /******************************Public*Routine******************************\ * PLGRUN *prunPlgRead32(prun, pjSrc, pjMask, pxlo, xLeft, xRght, xMask) * * Read the source, mask it, xlate colors and produce a run list * for a row of a 32BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ PLGRUN *prunPlgRead32( PLGDDA *pdda, PLGRUN *prun, BYTE *pjSrc, BYTE *pjMask, XLATEOBJ *pxlo, LONG xLeft, LONG xRght, LONG xMask) { DWORD *pdwSrc = (DWORD *) pjSrc; ULONG *pulMsk; ULONG ulMsk; ULONG iColor; LONG iMask; pdwSrc += xLeft; if (pjMask == (BYTE *) NULL) { if (pxlo == NULL) while (xLeft != xRght) { prun->iColor = *pdwSrc; prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); pdwSrc++; xLeft++; } else while (xLeft != xRght) { prun->iColor = ((XLATE *) pxlo)->ulTranslate(*pdwSrc); prun = prunPumpDDA(pdda, prun); vAdvXDDA(pdda); pdwSrc++; xLeft++; } return(prun); } // Compute initial state of mask pulMsk = ((DWORD *) pjMask) + (xMask >> 5); iMask = xMask & 31; ulMsk = *pulMsk; while (xLeft != xRght) { if (ulMsk & gaulMaskMono[iMask]) { iColor = *pdwSrc; if (pxlo == NULL) prun->iColor = iColor; else prun->iColor = ((XLATE *) pxlo)->ulTranslate(iColor); prun = prunPumpDDA(pdda, prun); } vAdvXDDA(pdda); pdwSrc++; xLeft++; iMask++; if (iMask & 32) { pulMsk++; ulMsk = *pulMsk; iMask = 0; } } return(prun); } static BYTE gajMask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; /******************************Public*Routine******************************\ * VOID vPlgWrite1(prun, prunEnd, pSurf, pco) * * Write the clipped run list of pels to the target 1BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vPlgWrite1( PLGRUN *prun, PLGRUN *prunEnd, SURFACE *pSurf, CLIPOBJ *pco) { BYTE *pjBase; BYTE *pjOff; CNTPOS *pcp; ULONG iColor; LONG yCurr; LONG yDist; LONG xCurr; LONG xDist; BYTE jMask; BYTE jTemp; BOOL bValid; // See if this can be handled without clipping. if (pco == (CLIPOBJ *) NULL) { while (prun != prunEnd) { iColor = prun->iColor ? (ULONG) -1L : 0L; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 3); jMask = gajMask[xCurr & 7]; jTemp = *pjOff; while (xDist != 0) { jTemp = (BYTE) ((jTemp & ~jMask) | (iColor & jMask)); xDist--; xCurr++; jMask >>= 1; if (jMask == (BYTE) 0) { *pjOff = jTemp; pjOff++; jTemp = *pjOff; jMask = gajMask[xCurr & 7]; } } *pjOff = jTemp; pjBase += pSurf->lDelta(); yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There is a clip region. Set up the clipping code. ((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, 100); RECTL rclClip; rclClip.left = POS_INFINITY; rclClip.top = POS_INFINITY; rclClip.right = NEG_INFINITY; rclClip.bottom = NEG_INFINITY; while (prun != prunEnd) { iColor = prun->iColor ? (ULONG) -1L : 0L; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr < rclClip.top) || (yCurr >= rclClip.bottom)) ((ECLIPOBJ *) pco)->vFindScan(&rclClip, yCurr); if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 3); jMask = gajMask[xCurr & 7]; bValid = ((xCurr >= 0) && (xCurr < pSurf->sizl().cx)); jTemp = bValid ? *pjOff : (BYTE) 0; while (xDist != 0) { if ((xCurr < rclClip.left) || (xCurr >= rclClip.right)) ((ECLIPOBJ *) pco)->vFindSegment(&rclClip, xCurr, yCurr); if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) jTemp = (BYTE) ((jTemp & ~jMask) | (iColor & jMask)); xDist--; xCurr++; jMask >>= 1; if (jMask == (BYTE) 0) { if (bValid) *pjOff = jTemp; jMask = gajMask[xCurr & 7]; pjOff++; bValid = ((xCurr >= 0) && (xCurr < pSurf->sizl().cx)); jTemp = bValid ? *pjOff : (BYTE) 0; } } if (bValid) *pjOff = jTemp; } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } } /******************************Public*Routine******************************\ * VOID vPlgWrite4(prun, prunEnd, pSurf, pco) * * Write the clipped run list of pels to the target 4BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vPlgWrite4( PLGRUN *prun, PLGRUN *prunEnd, SURFACE *pSurf, CLIPOBJ *pco) { BYTE *pjBase; BYTE *pjOff; CNTPOS *pcp; ULONG iColor; LONG yCurr; LONG yDist; LONG xCurr; LONG xDist; BYTE jMask; // See if this can be handled without clipping. if (pco == (CLIPOBJ *) NULL) { while (prun != prunEnd) { iColor = prun->iColor | (prun->iColor << 4); yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 1); jMask = (xCurr & 1) ? 0x0F : 0xF0; while (xDist != 0) { *pjOff = (BYTE) ((*pjOff & ~jMask) | (iColor & jMask)); jMask ^= 0xFF; if (jMask == 0xF0) pjOff++; xDist--; } pjBase += pSurf->lDelta(); yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There maybe a single rectangle to clip against. RECTL rclClip; if (pco->iDComplexity == DC_RECT) { rclClip = pco->rclBounds; while (prun != prunEnd) { yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; iColor = prun->iColor | (prun->iColor << 4); pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 1); jMask = (xCurr & 1) ? 0x0F : 0xF0; while (xDist != 0) { if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) *pjOff = (BYTE) ((*pjOff & ~jMask) | (iColor & jMask)); xDist--; xCurr++; jMask ^= 0xFF; if (jMask == 0xF0) pjOff++; } } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There is complex clipping. Set up the clipping code. ((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, 100); rclClip.left = POS_INFINITY; rclClip.top = POS_INFINITY; rclClip.right = NEG_INFINITY; rclClip.bottom = NEG_INFINITY; while (prun != prunEnd) { yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; iColor = prun->iColor | (prun->iColor << 4); pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr < rclClip.top) || (yCurr >= rclClip.bottom)) ((ECLIPOBJ *) pco)->vFindScan(&rclClip, yCurr); if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 1); jMask = (xCurr & 1) ? 0x0F : 0xF0; while (xDist != 0) { if ((xCurr < rclClip.left) || (xCurr >= rclClip.right)) ((ECLIPOBJ *) pco)->vFindSegment(&rclClip, xCurr, yCurr); if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) *pjOff = (BYTE) ((*pjOff & ~jMask) | (iColor & jMask)); xDist--; xCurr++; jMask ^= 0xFF; if (jMask == 0xF0) pjOff++; } } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } } /******************************Public*Routine******************************\ * VOID vPlgWrite8(prun, prunEnd, pso, pco) * * Write the clipped run list of pels to the target 8BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vPlgWrite8( PLGRUN *prun, PLGRUN *prunEnd, SURFACE *pSurf, CLIPOBJ *pco) { BYTE *pjBase; BYTE *pjOff; CNTPOS *pcp; ULONG iColor; LONG yCurr; LONG yDist; LONG xCurr; LONG xDist; // See if this can be handled without clipping. if (pco == (CLIPOBJ *) NULL) { while (prun != prunEnd) { iColor = prun->iColor; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { pjOff = pjBase + pcp->iPos; xDist = pcp->cCnt; while (xDist != 0) { *pjOff = (BYTE) iColor; pjOff++; xDist--; } pjBase += pSurf->lDelta(); yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There maybe a single rectangle to clip against. RECTL rclClip; if (pco->iDComplexity == DC_RECT) { rclClip = pco->rclBounds; while (prun != prunEnd) { yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; iColor = prun->iColor; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + xCurr; while (xDist != 0) { if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) *pjOff = (BYTE) iColor; xDist--; xCurr++; pjOff++; } } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There is complex clipping. Set up the clipping code. ((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, 100); rclClip.left = POS_INFINITY; rclClip.top = POS_INFINITY; rclClip.right = NEG_INFINITY; rclClip.bottom = NEG_INFINITY; while (prun != prunEnd) { yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; iColor = prun->iColor; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr < rclClip.top) || (yCurr >= rclClip.bottom)) ((ECLIPOBJ *) pco)->vFindScan(&rclClip, yCurr); if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + xCurr; while (xDist != 0) { if ((xCurr < rclClip.left) || (xCurr >= rclClip.right)) ((ECLIPOBJ *) pco)->vFindSegment(&rclClip, xCurr, yCurr); if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) *pjOff = (BYTE) iColor; xDist--; xCurr++; pjOff++; } } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } } /******************************Public*Routine******************************\ * VOID vPlgWrite16(prun, prunEnd, pSurf, pco) * * Write the clipped run list of pels to the target 16BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vPlgWrite16( PLGRUN *prun, PLGRUN *prunEnd, SURFACE *pSurf, CLIPOBJ *pco) { BYTE *pjBase; WORD *pwOff; CNTPOS *pcp; ULONG iColor; LONG yCurr; LONG yDist; LONG xCurr; LONG xDist; // See if this can be handled without clipping. if (pco == (CLIPOBJ *) NULL) { while (prun != prunEnd) { iColor = prun->iColor; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { pwOff = ((WORD *) pjBase) + pcp->iPos; xDist = pcp->cCnt; while (xDist != 0) { *pwOff = (WORD) iColor; xDist--; pwOff++; } pjBase += pSurf->lDelta(); yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There is a clip region. Set up the clipping code. ((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, 100); RECTL rclClip; rclClip.left = POS_INFINITY; rclClip.top = POS_INFINITY; rclClip.right = NEG_INFINITY; rclClip.bottom = NEG_INFINITY; while (prun != prunEnd) { yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; iColor = prun->iColor; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr < rclClip.top) || (yCurr >= rclClip.bottom)) ((ECLIPOBJ *) pco)->vFindScan(&rclClip, yCurr); if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pwOff = ((WORD *) pjBase) + xCurr; while (xDist != 0) { if ((xCurr < rclClip.left) || (xCurr >= rclClip.right)) ((ECLIPOBJ *) pco)->vFindSegment(&rclClip, xCurr, yCurr); if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) *pwOff = (WORD) iColor; xDist--; xCurr++; pwOff++; } } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } } /******************************Public*Routine******************************\ * VOID vPlgWrite24(prun, prunEnd, pSurf, pco) * * Write the clipped run list of pels to the target 24BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vPlgWrite24( PLGRUN *prun, PLGRUN *prunEnd, SURFACE *pSurf, CLIPOBJ *pco) { BYTE *pjBase; RGBTRIPLE *prgbOff; CNTPOS *pcp; ULONG iColor; LONG yCurr; LONG yDist; LONG xCurr; LONG xDist; // See if this can be handled without clipping. if (pco == (CLIPOBJ *) NULL) { while (prun != prunEnd) { iColor = prun->iColor; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { prgbOff = ((RGBTRIPLE *) pjBase) + pcp->iPos; xDist = pcp->cCnt; while (xDist != 0) { *prgbOff = *((RGBTRIPLE *) &iColor); prgbOff++; xDist--; } pjBase += pSurf->lDelta(); yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There is a clip region. Set up the clipping code. ((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, 100); RECTL rclClip; rclClip.left = POS_INFINITY; rclClip.top = POS_INFINITY; rclClip.right = NEG_INFINITY; rclClip.bottom = NEG_INFINITY; while (prun != prunEnd) { yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; iColor = prun->iColor; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr < rclClip.top) || (yCurr >= rclClip.bottom)) ((ECLIPOBJ *) pco)->vFindScan(&rclClip, yCurr); if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; prgbOff = ((RGBTRIPLE *) pjBase) + xCurr; while (xDist != 0) { if ((xCurr < rclClip.left) || (xCurr >= rclClip.right)) ((ECLIPOBJ *) pco)->vFindSegment(&rclClip, xCurr, yCurr); if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) *prgbOff = *((RGBTRIPLE *) &iColor); xDist--; xCurr++; prgbOff++; } } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } } /******************************Public*Routine******************************\ * VOID vPlgWrite32(prun, prunEnd, pSurf, pco) * * Write the clipped run list of pels to the target 32BPP surface. * * History: * 08-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vPlgWrite32( PLGRUN *prun, PLGRUN *prunEnd, SURFACE *pSurf, CLIPOBJ *pco) { BYTE *pjBase; DWORD *pdwOff; CNTPOS *pcp; ULONG iColor; LONG yCurr; LONG yDist; LONG xCurr; LONG xDist; // See if this can be handled without clipping. if (pco == (CLIPOBJ *) NULL) { while (prun != prunEnd) { iColor = prun->iColor; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { pdwOff = ((DWORD *) pjBase) + pcp->iPos; xDist = pcp->cCnt; while (xDist != 0) { *pdwOff = iColor; xDist--; pdwOff++; } pjBase += pSurf->lDelta(); yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There is a clip region. Set up the clipping code. ((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, 100); RECTL rclClip; rclClip.left = POS_INFINITY; rclClip.top = POS_INFINITY; rclClip.right = NEG_INFINITY; rclClip.bottom = NEG_INFINITY; while (prun != prunEnd) { yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; iColor = prun->iColor; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr < rclClip.top) || (yCurr >= rclClip.bottom)) ((ECLIPOBJ *) pco)->vFindScan(&rclClip, yCurr); if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pdwOff = ((DWORD *) pjBase) + xCurr; while (xDist != 0) { if ((xCurr < rclClip.left) || (xCurr >= rclClip.right)) ((ECLIPOBJ *) pco)->vFindSegment(&rclClip, xCurr, yCurr); if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) *pdwOff = iColor; xDist--; xCurr++; pdwOff++; } } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } } /******************************Public*Routine******************************\ * VOID vPlgWriteAND(prun, prunEnd, pSurf, pco) * * AND the clipped run list of pels to the target 1BPP surface. This can * be made much faster by noting that ANDing with 1's is a NOP. * * History: * 25-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vPlgWriteAND( PLGRUN *prun, PLGRUN *prunEnd, SURFACE *pSurf, CLIPOBJ *pco) { BYTE *pjBase; BYTE *pjOff; CNTPOS *pcp; ULONG iColor; LONG yCurr; LONG yDist; LONG xCurr; LONG xDist; BYTE jMask; BYTE jTemp; BOOL bValid; // See if this can be handled without clipping. if (pco == (CLIPOBJ *) NULL) { while (prun != prunEnd) { iColor = prun->iColor == 0 ? ~0L : 0L; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 3); jMask = gajMask[xCurr & 7]; jTemp = *pjOff; while (xDist >= 0) { jTemp &= ~((BYTE) (iColor & jMask)); xDist--; xCurr++; jMask >>= 1; if (jMask == (BYTE) 0) { *pjOff = jTemp; pjOff++; jTemp = *pjOff; jMask = gajMask[xCurr & 7]; } } *pjOff = jTemp; pjBase += pSurf->lDelta(); yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There is a clip region. Set up the clipping code. ((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, 100); RECTL rclClip; rclClip.left = POS_INFINITY; rclClip.top = POS_INFINITY; rclClip.right = NEG_INFINITY; rclClip.bottom = NEG_INFINITY; while (prun != prunEnd) { iColor = prun->iColor == 0 ? ~0L : 0L; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr < rclClip.top) || (yCurr >= rclClip.bottom)) ((ECLIPOBJ *) pco)->vFindScan(&rclClip, yCurr); if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 3); jMask = gajMask[xCurr & 7]; bValid = ((xCurr >= 0) && (xCurr < pSurf->sizl().cx)); jTemp = bValid ? *pjOff : (BYTE) 0; while (xDist >= 0) { if ((xCurr < rclClip.left) || (xCurr >= rclClip.right)) ((ECLIPOBJ *) pco)->vFindSegment(&rclClip, xCurr, yCurr); if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) jTemp &= ~((BYTE) (iColor & jMask)); xDist--; xCurr++; jMask >>= 1; if (jMask == (BYTE) 0) { if (bValid) *pjOff = jTemp; pjOff++; jMask = gajMask[xCurr & 7]; bValid = ((xCurr >= 0) && (xCurr < pSurf->sizl().cx)); jTemp = bValid ? *pjOff : (BYTE) 0; } } if (bValid) *pjOff = jTemp; } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } } /******************************Public*Routine******************************\ * VOID vPlgWriteOR(prun, prunEnd, pso, pco) * * OR the clipped run list of pels to the target 1BPP surface. This can * be much faster by noting that ORing with 0's is a NOP. * * History: * 25-Aug-1992 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ VOID vPlgWriteOR( PLGRUN *prun, PLGRUN *prunEnd, SURFACE *pSurf, CLIPOBJ *pco) { BYTE *pjBase; BYTE *pjOff; CNTPOS *pcp; ULONG iColor; LONG yCurr; LONG yDist; LONG xCurr; LONG xDist; BYTE jMask; BYTE jTemp; BOOL bValid; // See if this can be handled without clipping. if (pco == (CLIPOBJ *) NULL) { while (prun != prunEnd) { iColor = prun->iColor == 0 ? 0L : ~0L; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 3); jMask = gajMask[xCurr & 7]; jTemp = *pjOff; while (xDist >= 0) { jTemp |= ((BYTE) (iColor & jMask)); xDist--; xCurr++; jMask >>= 1; if (jMask == (BYTE) 0) { *pjOff = jTemp; pjOff++; jTemp = *pjOff; jMask = gajMask[xCurr & 7]; } } *pjOff = jTemp; pjBase += pSurf->lDelta(); yDist--; pcp++; } prun = (PLGRUN *) pcp; } return; } // There is a clip region. Set up the clipping code. ((ECLIPOBJ *) pco)->cEnumStart(FALSE, CT_RECTANGLES, CD_ANY, 100); RECTL rclClip; rclClip.left = POS_INFINITY; rclClip.top = POS_INFINITY; rclClip.right = NEG_INFINITY; rclClip.bottom = NEG_INFINITY; while (prun != prunEnd) { iColor = prun->iColor == 0 ? 0L : ~0L; yCurr = prun->cpY.iPos; yDist = prun->cpY.cCnt; pjBase = (BYTE *) pSurf->pvScan0() + pSurf->lDelta() * yCurr; pcp = &prun->cpX[0]; while (yDist != 0) { if ((yCurr < rclClip.top) || (yCurr >= rclClip.bottom)) ((ECLIPOBJ *) pco)->vFindScan(&rclClip, yCurr); if ((yCurr >= rclClip.top) && (yCurr < rclClip.bottom)) { xCurr = pcp->iPos; xDist = pcp->cCnt; pjOff = pjBase + (xCurr >> 3); jMask = gajMask[xCurr & 7]; bValid = ((xCurr >= 0) && (xCurr < pSurf->sizl().cx)); jTemp = bValid ? *pjOff : (BYTE) 0; while (xDist >= 0) { if ((xCurr < rclClip.left) || (xCurr >= rclClip.right)) ((ECLIPOBJ *) pco)->vFindSegment(&rclClip, xCurr, yCurr); if ((xCurr >= rclClip.left) && (xCurr < rclClip.right)) jTemp |= ((BYTE) (iColor & jMask)); xDist--; xCurr++; jMask >>= 1; if (jMask == (BYTE) 0) { if (bValid) *pjOff = jTemp; pjOff++; jMask = gajMask[xCurr & 7]; bValid = ((xCurr >= 0) && (xCurr < pSurf->sizl().cx)); jTemp = bValid ? *pjOff : (BYTE) 0; } } if (bValid) *pjOff = jTemp; } pjBase += pSurf->lDelta(); yCurr++; yDist--; pcp++; } prun = (PLGRUN *) pcp; } }