// Copyright (C) 1996 Keith Whitwell. // This file may only be copied under the terms of the GNU Library General // Public License - see the file COPYING in the lib3d distribution. #include #include #include #include "View8.H" DitherViewport::DitherViewport( Device *device, uint xscale, uint yscale ) : Viewport( device, xscale, yscale ), ditherTable(0) { } DitherViewport::DitherViewport( Exemplar e, int speed ) : Viewport( e, speed ), ditherTable(0) { } DitherViewport *DitherViewport::advertisment = new DitherViewport(Exemplar()); void DitherViewport::initializeColours() { // Set the device up with a broad range of colours which we will use // for dithering. // use 216 of 256 available colours - a good chance of not requiring // a private colour map under X. enum { redLevels = 6, blueLevels = 6, greenLevels = 6 }; cout << "DitherViewport::initializeColours()" << endl; int r,g,b; int index = 0; for (r = 0; r < redLevels; r++) { int red = r * 65535 / (redLevels-1); for (g = 0; g < greenLevels; g++) { int green = g * 65535 / (greenLevels-1); for (b = 0; b < blueLevels; b++) { int blue = b * 65535 / (blueLevels-1); colourTable[index++] = device->allocateColour(red, green, blue); } } } /* background = (((colourTable[0] * 256 + colourTable[0]) * 256 + colourTable[0]) * 256 + colourTable[0]); */ // Calculate the 2x2 dither patterns for 16*16*16=4096 approximated // colours. ditherTable = new uchar[16384]; index = 0; int redInc = (256 / (redLevels-1)); int greenInc = (256 / (greenLevels-1)); int blueInc = (256 / (blueLevels-1)); int dt[4] = { 0, 3, 2, 1 }; for (r = 0; r < 256; r += 16) { int red = r / redInc; int r_err = r % redInc; for (g = 0; g < 256; g += 16) { int green = g / greenInc; int g_err = g % greenInc; for (b = 0; b < 256; b += 16) { int blue = b / blueInc; int b_err = b % blueInc; for (int i = 0; i < 4; i++) { int dr = (r_err > (dt[i] * redInc) / 4) ? red+1 : red; int dg = (g_err > (dt[i] * greenInc) / 4) ? green+1 : green; int db = (b_err > (dt[i] * blueInc) / 4) ? blue+1 : blue; ditherTable[index++] = colourTable[((dr*greenLevels)+dg) *blueLevels+db]; } } } } } DitherViewport::~DitherViewport() { delete [] ditherTable; } Viewport * DitherViewport::clone( Device *device ) { uint depth = device->getDepth(); if (depth == 8) { // too strict? debug() << "Creating new viewport for 8 bit device." << endlog; return new DitherViewport( device, 1, 1 ); } else { debug() << "Warning: DitherViewport not suitable for " << depth << " bit device." << endlog; return 0; } } inline Colour DitherViewport::getColour( uint r, uint g, uint b ) { if (!ditherTable) initializeColours(); // A ditherViewport colour is now (as of 0.1.4) the four bytes of // the dither pattern packed into a single 32 bit integer. To use // a colour, just unpack the value passed to you. return *((Colour *)(ditherTable + (((r & 0xf0) << 6) | ((g & 0xf0) << 2) | ((b & 0xf0) >> 2)))); } #define EDGEMAX 1024 int ex[2*EDGEMAX]; uint ez[EDGEMAX]; void DitherViewport::flatPolygonZb(uint nr, PipelineData * const vertex[], Colour colour ) { static int poly = 0; poly++; if (nr == 3) { DitherViewport::flatTriangleZb( vertex, colour ); return; } uint i; int x1 = int(vertex[nr-1]->device.v[X]*256); int y1 = int(vertex[nr-1]->device.v[Y]); uint z1 = uint(vertex[nr-1]->device.v[Z]); int ymin = y1; int ymax = y1; // Need to find ymid in advance for ( int k = nr-2 ; k >= 0; k-- ) { int y = int(vertex[k]->device.v[Y]); if (y < ymin) ymin = y; if (y > ymax) ymax = y; } if (ymin == ymax) return; int ymid = (ymin + ymax) >> 1; int zmid = 0; // z value of rhs of polygon at ymid. for ( i = 0 ; i < nr; i++ ) { int dx; int x; // Start point for edge rasterization. int *ptr; // Into edge rasterization buffer. int x0 = x1; int y0 = y1; uint z0 = z1; y1 = int(vertex[i]->device.v[Y]); x1 = int(vertex[i]->device.v[X]*256); z1 = uint(vertex[i]->device.v[Z]); int dy = y1 - y0; if (dy == 0) continue; if (dy < 0) { if ( y0 == ymid ) { zmid = z0; } else if ( y0 >= ymid && y1 <= ymid ) { // Includes the middle scanline of the polygon. zmid = int(z0) + ((ymid - y0)*(int(z1) - int(z0))) / dy; } dy = -dy; ptr = ex + y1*2 + 1; dx = x0 - x1; x = x1 - 256; int xSlope = dx / dy; int k = dy+1; do { *ptr = x>>8; ptr += 2; x += xSlope; } while(--k); } else { // Left edge. We also want to interpolate the z coordinates. uint *zptr = ez + y0; uint z = z0 + zBuffer->getGenerationMask(); int dz = z1 - z0; int zSlope = dz / dy; int k = dy+1; ptr = ex + y0*2; x = x0; dx = x1 - x0; int xSlope = dx / dy; do { *ptr = x>>8; ptr += 2; x += xSlope; *zptr = z; zptr++; z += zSlope; } while (--k); } } zmid += zBuffer->getGenerationMask(); int xspan = (ex[(ymid<<1)+1] - ex[ymid<<1]); if (xspan <= 0) return; int zSlope = (zmid - int(ez[ymid])) / xspan; uchar *cptr = device->getBuffer() + ymin * device->getRowWidth(); uint *zptr = zBuffer->getBuffer() + ymin * zBuffer->getWidth(); int *exptr = ex + ymin * 2; const uchar *dptr = ((uchar *)&colour) + ((ymin & 1) << 1); for ( int y = ymin ; y < ymax ; y++ ) { int xmin = *exptr++; int i = *exptr++ - xmin; uint z; if (i >= 0) { uchar *cp = cptr + xmin; uint *zp = zptr + xmin; z = ez[y]; #if 1 int tmp = (uint(cp) ^ i) & 1; uchar l = dptr[tmp]; uchar h = dptr[tmp^1]; if ((i & 1) == 0) { zp--; cp--; goto mid; } do { if (z < zp[0]) { zp[0] = uint(z); cp[0] = l; } z += zSlope; mid: if (z < zp[1]) { zp[1] = uint(z); cp[1] = h; } z += zSlope; zp+=2; cp+=2; i -= 2; } while (i >= 0); #else while ( i >= 0 ) { if (z < zp[0]) { zp[0] = uint(z); cp[0] = colourTable[uint(z&0x00ffffff)>>19]; } z += zSlope; zp+=1; cp+=1; i-=1; } #endif } cptr += device->getRowWidth(); zptr += zBuffer->getWidth(); dptr = (uchar *)(ulong(dptr) ^ 0x02); } } void DitherViewport::lineZb(const DeviceVector &from, const DeviceVector &to, DeviceColour c) { uchar colour = c; // Just pick one of the four bytes - dont care // which. int dx = to.v[X] - from.v[X]; int dy = to.v[Y] - from.v[Y]; int dz = to.v[Z] - from.v[Z]; if (dx == 0 && dy == 0) { return; } int width = device->getWidth(); int ipy; int ymin, xmin; if (dy < 0) { ymin = to.v[Y]; ipy = - width; dy = -dy; } else { ymin = from.v[Y]; ipy = width; } int ipx; if (dx < 0) { xmin = to.v[X]; ipx = -1; dx = -dx; } else { xmin = from.v[X]; ipx = 1; } zBuffer->setDirty( xmin, ymin, xmin+dx, ymin+dy ); device->setDirty( xmin, ymin, xmin+dx, ymin+dy ); uchar *cptr = (device->getBuffer() + from.v[X] + from.v[Y]*width); uint *zptr = (zBuffer->getBuffer() + from.v[X] + from.v[Y] * width); uint z = from.v[Z] + zBuffer->getGenerationMask(); int ipxy = ipx + ipy; if (dx > dy) { int iE = dy * 2; int d = iE - dx; // (dy * 2) - dx int iNE = d - dx; // (dy - dx) * 2 int iZ = dz / dx; while (--dx) { if (z < *zptr) { *cptr = colour; *zptr = z; } z += iZ; if (d <= 0) { d += iE; cptr += ipx; zptr += ipx; } else { d += iNE; cptr += ipxy; zptr += ipxy; } } } else { int iN = dx * 2; int d = iN - dy; // (dx * 2) - dy int iNE = d - dy; // (dx - dy) * 2 int iZ = dz / dy; while (--dy) { if (z < *zptr) { *cptr = colour; *zptr = z; } z += iZ; if (d <= 0) { d += iN; cptr += ipy; zptr += ipy; } else { d += iNE; cptr += ipxy; zptr += ipxy; } } } } void DitherViewport::flatTriangleZb(PipelineData * const vertex[], Colour colour ) { int tx[3]; if (0) { DitherViewport::flatPolygonZb(3, vertex, colour); return; } int y0 = vertex[0]->device.v[Y]; int y1 = vertex[1]->device.v[Y]; int y2 = vertex[2]->device.v[Y]; int type; if (y0 > y1) { if (y1 > y2) { type = 1; tx[0] = 2; tx[1] = 1; tx[2] = 0; } else { if (y0 > y2) { type = 0; tx[0] = 1; tx[1] = 2; tx[2] = 0; } else { type = 1; tx[0] = 1; tx[1] = 0; tx[2] = 2; } } } else { if (y2 > y1) { type = 0; tx[0] = 0; tx[1] = 1; tx[2] = 2; } else { if (y0 > y2) { type = 0; tx[0] = 2; tx[1] = 0; tx[2] = 1; } else { type = 1; tx[0] = 0; tx[1] = 2; tx[2] = 1; } } } if_debug { debug() << "In y order: " << endlog; debug() << "\t" << vertex[tx[0]]->device << endlog; debug() << "\t" << vertex[tx[1]]->device << endlog; debug() << "\t" << vertex[tx[2]]->device << endlog; debug() << "type: " << type << endlog; } int dy = vertex[tx[2]]->device.v[Y] - vertex[tx[0]]->device.v[Y]; if (dy == 0) { if_debug { debug() << "Zero height triangle" << endlog; } return; } uint *zptr = ez + vertex[tx[0]]->device.v[Y]; uint z = vertex[tx[0]]->device.v[Z] + zBuffer->getGenerationMask(); int dz = vertex[tx[2]]->device.v[Z] - vertex[tx[0]]->device.v[Z]; int zSlope = dz / dy; int *xptr = ex + (vertex[tx[0]]->device.v[Y] * 2); int x = vertex[tx[0]]->device.v[X] * 256; int dx = vertex[tx[2]]->device.v[0] - vertex[tx[0]]->device.v[0]; int xSlope = (dx * 256) / dy; int k = dy+1; if (dx != 0) { do { *xptr = x >> 8; xptr += 2; x += xSlope; *zptr++ = z; z += zSlope; } while (--k); } else { int xx = x >> 8; do { *xptr = xx; xptr += 2; *zptr++ = z; z += zSlope; } while (--k); } xptr = ex + (vertex[tx[0]]->device.v[Y] * 2) + 1; dy = vertex[tx[1]]->device.v[Y] - vertex[tx[0]]->device.v[Y]; if (dy != 0) { x = vertex[tx[0]]->device.v[X] * 256; dx = vertex[tx[1]]->device.v[X] - vertex[tx[0]]->device.v[X]; xSlope = (dx * 256) / dy; if (dx != 0) { do { *xptr = x >> 8; xptr += 2; x += xSlope; } while (--dy); } else { int xx = x >> 8; do { *xptr = xx; xptr += 2; } while (--dy); } } dy = vertex[tx[2]]->device.v[Y] - vertex[tx[1]]->device.v[Y]; if (dy != 0) { x = vertex[tx[1]]->device.v[X] * 256; dx = vertex[tx[2]]->device.v[X] - vertex[tx[1]]->device.v[X]; xSlope = (dx * 256) / dy; if (dx != 0) { do { *xptr = x >> 8; xptr += 2; x += xSlope; } while (--dy); } else { int xx = x >> 8; do { *xptr = xx; xptr += 2; } while (--dy); } } else { *xptr = x >> 8; } uint zmid = uint(vertex[tx[1]]->device.v[Z]) + zBuffer->getGenerationMask(); int ymin = vertex[tx[0]]->device.v[Y]; int ymid = vertex[tx[1]]->device.v[Y]; int ymax = vertex[tx[2]]->device.v[Y]; uchar *cptr = device->getBuffer() + ymin * device->getRowWidth(); const uchar *dptr = ((uchar *)&colour) + ((ymin & 1) << 1); zptr = (uint *)(zBuffer->getBuffer()) + ymin * zBuffer->getWidth(); xptr = ex + ymin * 2; if (type == 1) { int xspan = (ex[(ymid<<1)+1] - ex[ymid<<1]); if (xspan <= 0) { return; } int zSlope = (int(zmid) - int(ez[ymid])) / xspan; /* // int foo = zSlope; cout << vertex[tx[0]]->device << endl; cout << vertex[tx[1]]->device << endl; cout << vertex[tx[2]]->device << endl; printf("Initial Z: %x After: %x Step: %d \tSlope: %d \n", vertex[tx[0]]->device.v[Z], vertex[tx[0]]->device.v[Z], foo, zSlope); */ for ( int y = ymin ; y < ymax ; y++ ) { int xmin = *xptr++; uint z; int i = (*xptr++ - xmin) - 1; if (i >= 0) { uchar *cp = cptr + xmin; uint *zp = zptr + xmin; z = ez[y]; int tmp = (uint(cp) ^ i) & 1; uchar l = dptr[tmp]; uchar h = dptr[tmp^1]; if ((i & 1) == 0) { zp--; cp--; goto mid2; } do { if (z < zp[0]) { zp[0] = uint(z); cp[0] = l; } z += zSlope; mid2: if (z < zp[1]) { zp[1] = uint(z); cp[1] = h; } z += zSlope; zp+=2; cp+=2; i -= 2; } while (i >= 0); } cptr += device->getRowWidth(); zptr += zBuffer->getWidth(); dptr = (uchar *)(ulong(dptr) ^ 0x02); } } else { int xspan = (ex[(ymid<<1)] - ex[(ymid<<1)+1]); if (xspan <= 0) { return; } int zSlope = (int(zmid) - int(ez[ymid])) / xspan; /* //int foo = zSlope; cout << vertex[tx[0]]->device << endl; cout << vertex[tx[1]]->device << endl; cout << vertex[tx[2]]->device << endl; printf("Initial Z: %x After: %x Step: %d \tSlope: %d \n", vertex[tx[0]]->device.v[Z], vertex[tx[0]]->device.v[Z], foo, zSlope); */ for ( int y = ymin ; y < ymax ; y++ ) { int xmax = *xptr++; int xmin = *xptr++; --xmax; int i = xmax - xmin; uint z; if (i >= 0) { uchar *cp = cptr + xmax; uint *zp = zptr + xmax; z = ez[y]; int tmp = (uint(cp) ^ i) & 1; uchar l = dptr[tmp]; uchar h = dptr[tmp^1]; if ((i & 1) == 0) { zp++; cp++; goto mid3; } do { if (z < zp[0]) { zp[0] = uint(z); cp[0] = l; } z += zSlope; mid3: if (z < *(zp-1)) { *(zp-1) = uint(z); *(cp-1) = h; } z += zSlope; zp-=2; cp-=2; i -= 2; } while (i >= 0); } cptr += device->getRowWidth(); zptr += zBuffer->getWidth(); dptr = (uchar *)(ulong(dptr) ^ 0x02); } } return; } /* * Display 4096 of the colours available through dithering on an 8bit * display. Appears as slices through a textbook RGB cube. * * Assumes a window larger than (300 x 256). */ void DitherViewport::drawColourSpace() { int i; uchar *dptr = device->getBuffer(); int wid = device->getRowWidth(); for (i = 0 ; i < 256 ; i+=2) { uint idx = getColour( i, i, i ); for (int y = 0 ; y < 2 ; y++) { for (int x = 0 ; x < 32 ; x++ ) { dptr[160+x+((i+y)*wid)] = *((uchar *)&idx+(x&1)+((y&1)*2)); } } } for (i = 0 ; i < 16384; i++) { uint idx =( (i & 1) // Dither x + (((i>>1)&1) * wid) // Dither y + (((i>>2)&15) * 2) // horizontal spans + (((i>>6)&15) * (wid * 2)) // arranged vertically + (((i>>10)&3) * (wid * 40)) // in tiles + (((i>>12) * 40))); // in 4 columns dptr[idx] = ditherTable[i]; } device->setDirty(0,0,device->getWidth(),device->getHeight()); } int ei[EDGEMAX]; void DitherViewport::smoothPolygonZb(uint nr, SmoothPipelineData * const vertex[], const ColourRamp &ramp ) { if (nr==3) { DitherViewport::smoothTriangleZb(vertex, ramp); return; } int x1 = vertex[nr-1]->device.v[X]; int y1 = vertex[nr-1]->device.v[Y]; uint z1 = uint(vertex[nr-1]->device.v[Z]); int i1 = vertex[nr-1]->intensity; int ymin = y1; int ymax = y1; // Need to find ymid in advance for ( int k = nr-2 ; k >= 0; k-- ) { int y = int(vertex[k]->device.v[Y]); if (y < ymin) ymin = y; if (y > ymax) ymax = y; } if (ymin == ymax) return; int ymid = (ymin + ymax) >> 1; int zmid = 0; // z value of rhs of polygon at ymid. int imid = 0; for (uint v = 0 ; v < nr; v++ ) { int x0 = x1; int y0 = y1; uint z0 = z1; int i0 = i1; y1 = vertex[v]->device.v[Y]; x1 = vertex[v]->device.v[X]; z1 = uint(vertex[v]->device.v[Z]); i1 = vertex[v]->intensity; int dy = y1 - y0; if (dy == 0) continue; if (dy < 0) { if ( y0 == ymid ) { zmid = z0; imid = i0; } else if ( y0 > ymid && y1 <= ymid ) { // Includes the middle scanline of the polygon. zmid = int(z0) + ((ymid - y0)*(int(z1) - int(z0))) / dy; imid = i0 + ((ymid - y0)*(i1 - i0)) / dy; } dy = -dy; int *xptr = ex + y1*2 + 1; int x = x1 * 256; int dx = (x0 * 256) - x; int xSlope = dx / dy; int k = dy+1; do { *xptr = x>>8; xptr += 2; x += xSlope; } while(--k); } else { // Left edge. We also want to interpolate z and intensity. uint *zptr = ez + y0; uint z = z0 + zBuffer->getGenerationMask(); int dz = z1 - z0; int zSlope = dz / dy; int k = dy+1; int *xptr = ex + y0*2 ; int x = x0 * 256; int dx = (x1 * 256) - x; int xSlope = dx / dy; int i = i0; int di = i1 - i0; int iSlope = di / dy; int *iptr = ei + y0; do { *xptr = x>>8; xptr += 2; x += xSlope; *zptr = z; zptr++; z += zSlope; *iptr = i; i += iSlope; iptr++; } while (--k); } } zmid += zBuffer->getGenerationMask(); int xspan = (ex[(ymid<<1)+1] - ex[ymid<<1]); if (xspan <= 0) return; int zSlope = (zmid - int(ez[ymid])) / xspan; int iSlope = (imid - ei[ymid]) / xspan; uchar *cptr = device->getBuffer() + ymin * device->getRowWidth(); uint *zptr = zBuffer->getBuffer() + ymin * zBuffer->getWidth(); int *xptr = ex + ymin * 2; const uchar *dptr = ((uchar *)ramp.getRamp()) + ((ymin & 1) << 1); for ( int y = ymin ; y < ymax ; y++ ) { int xmin = *xptr++; int wid = (*xptr++ - xmin) - 1; if (wid >= 0) { int i = ei[y]; uchar *cp = cptr + xmin; uint *zp = zptr + xmin; uint z = ez[y]; int tmp = (uint(cp) ^ wid) & 1; const uchar *tmp1 = dptr + tmp; const uchar *tmp2 = dptr + (tmp ^ 1); if ((wid & 1) == 0) { zp--; cp--; goto mid100; } do { if (z < zp[0]) { zp[0] = uint(z); cp[0] = tmp1[(i>>8)*4]; //cp[0] = (i>>8)*4; } z += zSlope; i += iSlope; mid100: if (z < zp[1]) { zp[1] = uint(z); cp[1] = tmp2[(i>>8)*4]; //cp[1] = (i>>8)*4; } z += zSlope; i += iSlope; zp+=2; cp+=2; wid -= 2; } while (wid >= 0); } cptr += device->getRowWidth(); zptr += zBuffer->getWidth(); dptr = (uchar *)(ulong(dptr) ^ 0x02); } } void DitherViewport::smoothTriangleZb(SmoothPipelineData * const vertex[], const ColourRamp &ramp ) { if (0) { DitherViewport::smoothPolygonZb(3, vertex, ramp); return; } int tx[3]; int y0 = vertex[0]->device.v[Y]; int y1 = vertex[1]->device.v[Y]; int y2 = vertex[2]->device.v[Y]; int type; if (y0 > y1) { if (y1 > y2) { type = 1; tx[0] = 2; tx[1] = 1; tx[2] = 0; } else { if (y0 > y2) { type = 0; tx[0] = 1; tx[1] = 2; tx[2] = 0; } else { type = 1; tx[0] = 1; tx[1] = 0; tx[2] = 2; } } } else { if (y2 > y1) { type = 0; tx[0] = 0; tx[1] = 1; tx[2] = 2; } else { if (y0 > y2) { type = 0; tx[0] = 2; tx[1] = 0; tx[2] = 1; } else { type = 1; tx[0] = 0; tx[1] = 2; tx[2] = 1; } } } int dy = vertex[tx[2]]->device.v[Y] - vertex[tx[0]]->device.v[Y]; if (dy == 0) return; uint *zptr = ez + vertex[tx[0]]->device.v[Y]; uint z = vertex[tx[0]]->device.v[Z] + zBuffer->getGenerationMask(); int dz = vertex[tx[2]]->device.v[Z] - vertex[tx[0]]->device.v[Z]; int zSlope = dz / dy; int *iptr = ei + vertex[tx[0]]->device.v[Y]; int i = vertex[tx[0]]->intensity; int di = (vertex[tx[2]]->intensity) - i; int iSlope = di / dy; int k = dy+1; int *xptr = ex + (vertex[tx[0]]->device.v[Y] * 2); int x = vertex[tx[0]]->device.v[X] * 256; int dx = vertex[tx[2]]->device.v[0] - vertex[tx[0]]->device.v[0]; if (dx != 0) { int xSlope = (dx * 256) / dy; do { *xptr = x >> 8; xptr += 2; x += xSlope; *zptr++ = z; z += zSlope; *iptr = i; i += iSlope; iptr++; } while (--k); } else { int xx = x >> 8; do { *xptr = xx; xptr += 2; *zptr++ = z; z += zSlope; *iptr = i; i += iSlope; iptr++; } while (--k); } xptr = ex + (vertex[tx[0]]->device.v[Y] * 2) + 1; dy = vertex[tx[1]]->device.v[Y] - vertex[tx[0]]->device.v[Y]; if (dy != 0) { x = vertex[tx[0]]->device.v[X] * 256; dx = vertex[tx[1]]->device.v[X] - vertex[tx[0]]->device.v[X]; if (dx != 0) { int xSlope = (dx * 256) / dy; do { *xptr = x >> 8; xptr += 2; x += xSlope; } while (--dy); } else { int xx = x >> 8; do { *xptr = xx; xptr += 2; } while (--dy); } } dy = vertex[tx[2]]->device.v[Y] - vertex[tx[1]]->device.v[Y]; if (dy != 0) { x = vertex[tx[1]]->device.v[X] * 256; dx = vertex[tx[2]]->device.v[X] - vertex[tx[1]]->device.v[X]; if (dx != 0) { int xSlope = (dx * 256) / dy; do { *xptr = x >> 8; xptr += 2; x += xSlope; } while (--dy); } else { int xx = x >> 8; do { *xptr = xx; xptr += 2; } while (--dy); } } else { *xptr = x >> 8; } uint zmid = uint(vertex[tx[1]]->device.v[Z]) + zBuffer->getGenerationMask(); int imid = vertex[tx[1]]->intensity; int ymin = vertex[tx[0]]->device.v[Y]; int ymid = vertex[tx[1]]->device.v[Y]; int ymax = vertex[tx[2]]->device.v[Y]; uchar *cptr = device->getBuffer() + ymin * device->getRowWidth(); const uchar *dptr = ((uchar *)ramp.getRamp()) + ((ymin & 1) << 1); zptr = (uint *)(zBuffer->getBuffer()) + ymin * zBuffer->getWidth(); xptr = ex + ymin * 2; if (type == 1) { int xspan = (ex[(ymid<<1)+1] - ex[ymid<<1]); if (xspan <= 0) return; int zSlope = (int(zmid) - int(ez[ymid])) / xspan; int iSlope = (imid - ei[ymid]) / xspan; for ( int y = ymin ; y < ymax ; y++ ) { int xmin = *xptr++; int wid = (*xptr++ - xmin) - 1; if (wid >= 0) { int i = ei[y]; uchar *cp = cptr + xmin; uint *zp = zptr + xmin; uint z = ez[y]; int tmp1 = (uint(cp) ^ wid) & 1; int tmp2 = tmp1 ^ 1; if ((wid & 1) == 0) { zp--; cp--; goto mid100a; } do { if (z < zp[0]) { zp[0] = uint(z); cp[0] = dptr[(i>>8)*4+tmp1]; //cp[0] = (i>>8)*4; } z += zSlope; i += iSlope; mid100a: if (z < zp[1]) { zp[1] = uint(z); cp[1] = dptr[(i>>8)*4+tmp2]; //cp[1] = (i>>8)*4; } z += zSlope; i += iSlope; zp+=2; cp+=2; wid -= 2; } while (wid >= 0); } cptr += device->getRowWidth(); zptr += zBuffer->getWidth(); dptr = (uchar *)(ulong(dptr) ^ 0x02); } } else { int xspan = (ex[(ymid<<1)] - ex[(ymid<<1)+1]); if (xspan <= 0) return; int zSlope = (int(zmid) - int(ez[ymid])) / xspan; int iSlope = (imid - ei[ymid]) / xspan; for ( int y = ymin ; y < ymax ; y++ ) { int xmax = *xptr++; int xmin = *xptr++; --xmax; int wid = xmax - xmin; if (wid >= 0) { int i = ei[y]; uchar *cp = cptr + xmax; uint *zp = zptr + xmax; uint z = ez[y]; int tmp1 = (uint(cp) ^ wid) & 1; int tmp2 = tmp1 ^ 1; if ((wid & 1) == 0) { zp++; cp++; goto mid100b; } do { if (z < zp[0]) { zp[0] = uint(z); cp[0] = dptr[(i>>8)*4+tmp1]; //cp[0] = (i>>8)*4; } z += zSlope; i += iSlope; mid100b: if (z < *(zp-1)) { *(zp-1) = uint(z); *(cp-1) = dptr[(i>>8)*4+tmp2]; //*(cp-1) = (i>>8)*4; } z += zSlope; i += iSlope; zp-=2; cp-=2; wid -= 2; } while (wid >= 0); } cptr += device->getRowWidth(); zptr += zBuffer->getWidth(); dptr = (uchar *)(ulong(dptr) ^ 0x02); } } return; }