private void scanline(int y, float l[], float r[]) {
    //System.out.println("scanline " + y);
    for (int i = 0; i < vertexCount; i++) {  // should be moved later
      sp[i] = 0; sdp[i] = 0;
    }

    // this rounding doesn't seem to be relevant with smooth
    int lx = (int) (l[X] + 0.49999f);  // ceil(l[X]-.5);
    if (lx < 0) lx = 0;
    int rx = (int) (r[X] - 0.5f);
    if (rx > width1) rx = width1;

    if (lx > rx) return;

    if (smooth) {
      int mody = MODYRES(y);

      aaleft[mody] = lx;
      aaright[mody] = rx;

      if (firstModY == -1) {
        firstModY = mody;
        aaleftmin = lx; aaleftmax = lx;
        aarightmin = rx; aarightmax = rx;

      } else {
        if (aaleftmin > aaleft[mody]) aaleftmin = aaleft[mody];
        if (aaleftmax < aaleft[mody]) aaleftmax = aaleft[mody];
        if (aarightmin > aaright[mody]) aarightmin = aaright[mody];
        if (aarightmax < aaright[mody]) aarightmax = aaright[mody];
      }

      lastModY = mody;  // moved up here (before the return) 031001
      // not the eighth (or lastY) line, so not scanning this time
      if ((mody != SUBYRES1) && (y != lastY)) return;
      //lastModY = mody;  // eeK! this was missing
      //return;

      //if (y == lastY) {
      //System.out.println("y is lasty");
      //}
      //lastModY = mody;
      aaleftfull = aaleftmax/SUBXRES + 1;
      aarightfull = aarightmin/SUBXRES - 1;
    }

    // this is the setup, based on lx
    incrementalize_x(l, r, sp, sdp, lx);
    //System.out.println(l[V] + " " + r[V] + " " +sp[V] + " " +sdp[V]);

    // scan in x, generating pixels
    // using parent.width to get actual pixel index
    // rather than scaled by smooth factor
    int offset = smooth ? parent.width * (y / SUBYRES) : parent.width*y;

    int truelx = 0, truerx = 0;
    if (smooth) {
      truelx = lx / SUBXRES;
      truerx = (rx + SUBXRES1) / SUBXRES;

      lx = aaleftmin / SUBXRES;
      rx = (aarightmax + SUBXRES1) / SUBXRES;
      if (lx < 0) lx = 0;
      if (rx > parent.width1) rx = parent.width1;
    }

//    System.out.println("P3D interp uv " + interpUV + " " +
//                       vertices[2][U] + " " + vertices[2][V]);

    interpX = false;
    int tr, tg, tb, ta;
    //System.out.println("lx: "+lx + "\nrx: "+rx);
    for (int x = lx; x <= rx; x++) {

      // added == because things on same plane weren't replacing each other
      // makes for strangeness in 3D [ewj: yup!], but totally necessary for 2D
      //if (noDepthTest || (sp[Z] < zbuffer[offset+x])) {
      if (noDepthTest || (sp[Z] <= zbuffer[offset+x])) {
        //if (true) {

        // map texture based on U, V coords in sp[U] and sp[V]
        if (interpUV) {
          int tu = (int)sp[U];
          int tv = (int)sp[V];

          if (tu > twidth1) tu = twidth1;
          if (tv > theight1) tv = theight1;
          if (tu < 0) tu = 0;
          if (tv < 0) tv = 0;

          int txy = tv*twidth + tu;
          //System.out.println("tu: "+tu+" ; tv: "+tv+" ; txy: "+txy);
          float[] uv = new float[2];
          txy = getTextureIndex(x, y*1.0f/SUBYRES, uv);
          //          txy = getTextureIndex(x* 1.0f/SUBXRES, y*1.0f/SUBYRES, uv);

          tu = (int)uv[0]; tv = (int)uv[1];
          //          if (tu > twidth1) tu = twidth1;
          //          if (tv > theight1) tv = theight1;
          //          if (tu < 0) tu = 0;
          //          if (tv < 0) tv = 0;
          txy = twidth*tv + tu;
          //          if (EWJORDAN) System.out.println("x/y/txy:"+x + " " + y + " " +txy);
          //PApplet.println(sp);

          //smooth = true;
          if (smooth || texture_smooth) {
            //if (FRY) System.out.println("sp u v = " + sp[U] + " " + sp[V]);
            //System.out.println("sp u v = " + sp[U] + " " + sp[V]);
            // tuf1/tvf1 is the amount of coverage for the adjacent
            // pixel, which is the decimal percentage.
            //            int tuf1 = (int) (255f * (sp[U] - (float)tu));
            //            int tvf1 = (int) (255f * (sp[V] - (float)tv));

            int tuf1 = (int) (255f * (uv[0] - tu));
            int tvf1 = (int) (255f * (uv[1] - tv));

            // the closer sp[U or V] is to the decimal being zero
            // the more coverage it should get of the original pixel
            int tuf = 255 - tuf1;
            int tvf = 255 - tvf1;

            // this code sucks! filled with bugs and slow as hell!
            int pixel00 = tpixels[txy];
            int pixel01 = (tv < theight1) ? tpixels[txy + twidth] : tpixels[txy];
            int pixel10 = (tu < twidth1)  ? tpixels[txy + 1]      : tpixels[txy];
            int pixel11 = ((tv < theight1) && (tu < twidth1)) ? tpixels[txy + twidth + 1] : tpixels[txy];
            //System.out.println("1: "+pixel00);
            //check
            int p00, p01, p10, p11;
            int px0, px1; //, pxy;

            if (tformat == ALPHA) {
              px0 = (pixel00*tuf + pixel10*tuf1) >> 8;
              px1 = (pixel01*tuf + pixel11*tuf1) >> 8;
              ta = (((px0*tvf + px1*tvf1) >> 8) *
                    (interpARGB ? ((int) (sp[A]*255)) : a2orig)) >> 8;
            } else if (tformat == ARGB) {
              p00 = (pixel00 >> 24) & 0xff;
              p01 = (pixel01 >> 24) & 0xff;
              p10 = (pixel10 >> 24) & 0xff;
              p11 = (pixel11 >> 24) & 0xff;

              px0 = (p00*tuf + p10*tuf1) >> 8;
              px1 = (p01*tuf + p11*tuf1) >> 8;
              ta = (((px0*tvf + px1*tvf1) >> 8) *
                    (interpARGB ? ((int) (sp[A]*255)) : a2orig)) >> 8;
            } else {  // RGB image, no alpha
              //ACCTEX: Getting here when smooth is on
              ta = interpARGB ? ((int) (sp[A]*255)) : a2orig;
              //System.out.println("4: "+ta + " " +interpARGB + " " + sp[A] + " " + a2orig);
              //check
            }

            if ((tformat == RGB) || (tformat == ARGB)) {
              p00 = (pixel00 >> 16) & 0xff;  // red
              p01 = (pixel01 >> 16) & 0xff;
              p10 = (pixel10 >> 16) & 0xff;
              p11 = (pixel11 >> 16) & 0xff;

              px0 = (p00*tuf + p10*tuf1) >> 8;
              px1 = (p01*tuf + p11*tuf1) >> 8;
              tr = (((px0*tvf + px1*tvf1) >> 8) * (interpARGB ? ((int) (sp[R]*255)) : r2)) >> 8;

              p00 = (pixel00 >> 8) & 0xff;  // green
              p01 = (pixel01 >> 8) & 0xff;
              p10 = (pixel10 >> 8) & 0xff;
              p11 = (pixel11 >> 8) & 0xff;

              px0 = (p00*tuf + p10*tuf1) >> 8;
              px1 = (p01*tuf + p11*tuf1) >> 8;
              tg = (((px0*tvf + px1*tvf1) >> 8) * (interpARGB ? ((int) (sp[G]*255)) : g2)) >> 8;


              p00 = pixel00 & 0xff;  // blue
              p01 = pixel01 & 0xff;
              p10 = pixel10 & 0xff;
              p11 = pixel11 & 0xff;

              px0 = (p00*tuf + p10*tuf1) >> 8;
              px1 = (p01*tuf + p11*tuf1) >> 8;
              tb = (((px0*tvf + px1*tvf1) >> 8) * (interpARGB ? ((int) (sp[B]*255)) : b2)) >> 8;
              //System.out.println("5: "+tr + " " + tg + " " +tb);
              //check
            } else {  // alpha image, only use current fill color
              if (interpARGB) {
                tr = (int) (sp[R] * 255);
                tg = (int) (sp[G] * 255);
                tb = (int) (sp[B] * 255);
              } else {
                tr = r2;
                tg = g2;
                tb = b2;
              }
            }

            // get coverage for pixel if smooth
            // checks smooth again here because of
            // hints[SMOOTH_IMAGES] used up above
            int weight = smooth ? coverage(x) : 255;
            if (weight != 255) ta = (ta*weight) >> 8;
            //System.out.println(ta);
            //System.out.println("8");
            //check
          } else {  // no smooth, just get the pixels
            int tpixel = tpixels[txy];
            // TODO i doubt splitting these guys really gets us
            // all that much speed.. is it worth it?
            if (tformat == ALPHA) {
              ta = tpixel;
              if (interpARGB) {
                tr = (int) (sp[R]*255);
                tg = (int) (sp[G]*255);
                tb = (int) (sp[B]*255);
                if (sp[A] != 1) {
                  ta = (((int) (sp[A]*255)) * ta) >> 8;
                }
              } else {
                tr = r2;
                tg = g2;
                tb = b2;
                ta = (a2orig * ta) >> 8;
              }

            } else {  // RGB or ARGB
              ta = (tformat == RGB) ? 255 : (tpixel >> 24) & 0xff;
              if (interpARGB) {
                tr = (((int) (sp[R]*255)) * ((tpixel >> 16) & 0xff)) >> 8;
                tg = (((int) (sp[G]*255)) * ((tpixel >> 8) & 0xff)) >> 8;
                tb = (((int) (sp[B]*255)) * ((tpixel) & 0xff)) >> 8;
                ta = (((int) (sp[A]*255)) * ta) >> 8;
              } else {
                tr = (r2 * ((tpixel >> 16) & 0xff)) >> 8;
                tg = (g2 * ((tpixel >> 8) & 0xff)) >> 8;
                tb = (b2 * ((tpixel) & 0xff)) >> 8;
                ta = (a2orig * ta) >> 8;
              }
            }
          }

          if ((ta == 254) || (ta == 255)) {  // if (ta & 0xf8) would be good
            // no need to blend
            pixels[offset+x] = 0xff000000 | (tr << 16) | (tg << 8) | tb;
            zbuffer[offset+x] = sp[Z];
          } else {
            // blend with pixel on screen
            int a1 = 255-ta;
            int r1 = (pixels[offset+x] >> 16) & 0xff;
            int g1 = (pixels[offset+x] >> 8) & 0xff;
            int b1 = (pixels[offset+x]) & 0xff;


            pixels[offset+x] =
              0xff000000 |
              (((tr*ta + r1*a1) >> 8) << 16) |
              ((tg*ta + g1*a1) & 0xff00) |
              ((tb*ta + b1*a1) >> 8);

            //System.out.println("17");
            //check
            if (ta > ZBUFFER_MIN_COVERAGE) zbuffer[offset+x] = sp[Z];
          }

          //System.out.println("18");
          //check
        } else {  // no image applied
          int weight = smooth ? coverage(x) : 255;

          if (interpARGB) {
            r2 = (int) (sp[R] * 255);
            g2 = (int) (sp[G] * 255);
            b2 = (int) (sp[B] * 255);
            if (sp[A] != 1) weight = (weight * ((int) (sp[A] * 255))) >> 8;
            if (weight == 255) {
              rgba = 0xff000000 | (r2 << 16) | (g2 << 8) | b2;
            }
          } else {
            if (a2orig != 255) weight = (weight * a2orig) >> 8;
          }

          if (weight == 255) {
            // no blend, no aa, just the rgba
            pixels[offset+x] = rgba;
            zbuffer[offset+x] = sp[Z];

          } else {
            int r1 = (pixels[offset+x] >> 16) & 0xff;
            int g1 = (pixels[offset+x] >> 8) & 0xff;
            int b1 = (pixels[offset+x]) & 0xff;
            a2 = weight;

            int a1 = 255 - a2;
            pixels[offset+x] = (0xff000000 |
                                ((r1*a1 + r2*a2) >> 8) << 16 |
                                // use & instead of >> and << below
                                ((g1*a1 + g2*a2) >> 8) << 8 |
                                ((b1*a1 + b2*a2) >> 8));

            if (a2 > ZBUFFER_MIN_COVERAGE) zbuffer[offset+x] = sp[Z];
          }
        }
      }
      // if smooth enabled, don't increment values
      // for the pixel in the stretch out version
      // of the scanline used to get smooth edges.
      if (!smooth || ((x >= truelx) && (x <= truerx))) {
        //if (!smooth)
        increment(sp, sdp);
      }