~ubuntu-branches/ubuntu/precise/arduino/precise

« back to all changes in this revision

Viewing changes to src/processing/core/PPolygon.java

  • Committer: Bazaar Package Importer
  • Author(s): Scott Howard
  • Date: 2010-04-13 22:32:24 UTC
  • Revision ID: james.westby@ubuntu.com-20100413223224-jduxnd0xxnkkda02
Tags: upstream-0018+dfsg
ImportĀ upstreamĀ versionĀ 0018+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
 
2
 
 
3
/*
 
4
  Part of the Processing project - http://processing.org
 
5
 
 
6
  Copyright (c) 2004-08 Ben Fry and Casey Reas
 
7
  Copyright (c) 2001-04 Massachusetts Institute of Technology
 
8
 
 
9
  This library is free software; you can redistribute it and/or
 
10
  modify it under the terms of the GNU Lesser General Public
 
11
  License as published by the Free Software Foundation; either
 
12
  version 2.1 of the License, or (at your option) any later version.
 
13
 
 
14
  This library is distributed in the hope that it will be useful,
 
15
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
  Lesser General Public License for more details.
 
18
 
 
19
  You should have received a copy of the GNU Lesser General
 
20
  Public License along with this library; if not, write to the
 
21
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 
22
  Boston, MA  02111-1307  USA
 
23
*/
 
24
 
 
25
package processing.core;
 
26
 
 
27
 
 
28
/**
 
29
 * Z-buffer polygon rendering object used by PGraphics2D.
 
30
 */
 
31
public class PPolygon implements PConstants {
 
32
 
 
33
  static final int DEFAULT_SIZE = 64; // this is needed for spheres
 
34
  float vertices[][] = new float[DEFAULT_SIZE][VERTEX_FIELD_COUNT];
 
35
  int vertexCount;
 
36
 
 
37
  float r[]   = new float[DEFAULT_SIZE]; // storage used by incrementalize
 
38
  float dr[]  = new float[DEFAULT_SIZE];
 
39
  float l[]   = new float[DEFAULT_SIZE]; // more storage for incrementalize
 
40
  float dl[]  = new float[DEFAULT_SIZE];
 
41
  float sp[]  = new float[DEFAULT_SIZE]; // temporary storage for scanline
 
42
  float sdp[] = new float[DEFAULT_SIZE];
 
43
 
 
44
  protected boolean interpX;
 
45
  protected boolean interpUV; // is this necessary? could just check timage != null
 
46
  protected boolean interpARGB;
 
47
 
 
48
  private int rgba;
 
49
  private int r2, g2, b2, a2, a2orig;
 
50
 
 
51
  PGraphics parent;
 
52
  int[] pixels;
 
53
  // the parent's width/height,
 
54
  // or if smooth is enabled, parent's w/h scaled
 
55
  // up by the smooth dimension
 
56
  int width, height;
 
57
  int width1, height1;
 
58
 
 
59
  PImage timage;
 
60
  int[] tpixels;
 
61
  int theight, twidth;
 
62
  int theight1, twidth1;
 
63
  int tformat;
 
64
 
 
65
  // for anti-aliasing
 
66
  static final int SUBXRES  = 8;
 
67
  static final int SUBXRES1 = 7;
 
68
  static final int SUBYRES  = 8;
 
69
  static final int SUBYRES1 = 7;
 
70
  static final int MAX_COVERAGE = SUBXRES * SUBYRES;
 
71
 
 
72
  boolean smooth;
 
73
  int firstModY;
 
74
  int lastModY;
 
75
  int lastY;
 
76
  int aaleft[] = new int[SUBYRES];
 
77
  int aaright[] = new int[SUBYRES];
 
78
  int aaleftmin, aarightmin;
 
79
  int aaleftmax, aarightmax;
 
80
  int aaleftfull, aarightfull;
 
81
 
 
82
  final private int MODYRES(int y) {
 
83
    return (y & SUBYRES1);
 
84
  }
 
85
 
 
86
 
 
87
  public PPolygon(PGraphics iparent) {
 
88
    parent = iparent;
 
89
    reset(0);
 
90
  }
 
91
 
 
92
 
 
93
  protected void reset(int count) {
 
94
    vertexCount = count;
 
95
    interpX = true;
 
96
//    interpZ = true;
 
97
    interpUV = false;
 
98
    interpARGB = true;
 
99
    timage = null;
 
100
  }
 
101
 
 
102
 
 
103
  protected float[] nextVertex() {
 
104
    if (vertexCount == vertices.length) {
 
105
      float temp[][] = new float[vertexCount<<1][VERTEX_FIELD_COUNT];
 
106
      System.arraycopy(vertices, 0, temp, 0, vertexCount);
 
107
      vertices = temp;
 
108
 
 
109
      r   = new float[vertices.length];
 
110
      dr  = new float[vertices.length];
 
111
      l   = new float[vertices.length];
 
112
      dl  = new float[vertices.length];
 
113
      sp  = new float[vertices.length];
 
114
      sdp = new float[vertices.length];
 
115
    }
 
116
    return vertices[vertexCount++];  // returns v[0], sets vc to 1
 
117
  }
 
118
 
 
119
 
 
120
  /**
 
121
   * Return true if this vertex is redundant. If so, will also
 
122
   * decrement the vertex count.
 
123
   */
 
124
  /*
 
125
  public boolean redundantVertex(float x, float y, float z) {
 
126
    // because vertexCount will be 2 when setting vertex[1]
 
127
    if (vertexCount < 2) return false;
 
128
 
 
129
    // vertexCount-1 is the current vertex that would be used
 
130
    // vertexCount-2 would be the previous feller
 
131
    if ((Math.abs(vertices[vertexCount-2][MX] - x) < EPSILON) &&
 
132
        (Math.abs(vertices[vertexCount-2][MY] - y) < EPSILON) &&
 
133
        (Math.abs(vertices[vertexCount-2][MZ] - z) < EPSILON)) {
 
134
      vertexCount--;
 
135
      return true;
 
136
    }
 
137
    return false;
 
138
  }
 
139
  */
 
140
 
 
141
 
 
142
  protected void texture(PImage image) {
 
143
    this.timage = image;
 
144
 
 
145
    if (image != null) {
 
146
      this.tpixels = image.pixels;
 
147
      this.twidth = image.width;
 
148
      this.theight = image.height;
 
149
      this.tformat = image.format;
 
150
 
 
151
      twidth1 = twidth - 1;
 
152
      theight1 = theight - 1;
 
153
      interpUV = true;
 
154
      
 
155
    } else {
 
156
      interpUV = false;      
 
157
    }
 
158
  }
 
159
 
 
160
 
 
161
  protected void renderPolygon(float[][] v, int count) {
 
162
    vertices = v;
 
163
    vertexCount = count;
 
164
 
 
165
    if (r.length < vertexCount) {
 
166
      r   = new float[vertexCount]; // storage used by incrementalize
 
167
      dr  = new float[vertexCount];
 
168
      l   = new float[vertexCount]; // more storage for incrementalize
 
169
      dl  = new float[vertexCount];
 
170
      sp  = new float[vertexCount]; // temporary storage for scanline
 
171
      sdp = new float[vertexCount];
 
172
    }
 
173
 
 
174
    render();
 
175
    checkExpand();
 
176
  }
 
177
 
 
178
 
 
179
  protected void renderTriangle(float[] v1, float[] v2, float[] v3) {
 
180
    // Calling code will have already done reset(3).
 
181
    // Can't do it here otherwise would nuke any texture settings.
 
182
 
 
183
    vertices[0] = v1;
 
184
    vertices[1] = v2;
 
185
    vertices[2] = v3;
 
186
    
 
187
    render();
 
188
    checkExpand();
 
189
  }
 
190
  
 
191
  
 
192
  protected void checkExpand() {
 
193
    if (smooth) {
 
194
      for (int i = 0; i < vertexCount; i++) {
 
195
        vertices[i][TX] /= SUBXRES;
 
196
        vertices[i][TY] /= SUBYRES;
 
197
      }
 
198
    }
 
199
  }
 
200
  
 
201
  
 
202
  protected void render() {
 
203
    if (vertexCount < 3) return;
 
204
 
 
205
    // these may have changed due to a resize()
 
206
    // so they should be refreshed here
 
207
    pixels = parent.pixels;
 
208
    //zbuffer = parent.zbuffer;
 
209
 
 
210
//    noDepthTest = parent.hints[DISABLE_DEPTH_TEST];
 
211
    smooth = parent.smooth;
 
212
 
 
213
    // by default, text turns on smooth for the textures
 
214
    // themselves. but this should be shut off if the hint
 
215
    // for DISABLE_TEXT_SMOOTH is set.
 
216
//    texture_smooth = true;
 
217
 
 
218
    width = smooth ? parent.width*SUBXRES : parent.width;
 
219
    height = smooth ? parent.height*SUBYRES : parent.height;
 
220
 
 
221
    width1 = width - 1;
 
222
    height1 = height - 1;
 
223
 
 
224
    if (!interpARGB) {
 
225
      r2 = (int) (vertices[0][R] * 255);
 
226
      g2 = (int) (vertices[0][G] * 255);
 
227
      b2 = (int) (vertices[0][B] * 255);
 
228
      a2 = (int) (vertices[0][A] * 255);
 
229
      a2orig = a2; // save an extra copy
 
230
      rgba = 0xff000000 | (r2 << 16) | (g2 << 8) | b2;
 
231
    }
 
232
 
 
233
    for (int i = 0; i < vertexCount; i++) {
 
234
      r[i] = 0; dr[i] = 0; l[i] = 0; dl[i] = 0;
 
235
    }
 
236
 
 
237
    /*
 
238
    // hack to not make polygons fly into the screen
 
239
    if (parent.hints[DISABLE_FLYING_POO]) {
 
240
      float nwidth2 = -width * 2;
 
241
      float nheight2 = -height * 2;
 
242
      float width2 = width * 2;
 
243
      float height2 = height * 2;
 
244
      for (int i = 0; i < vertexCount; i++) {
 
245
        if ((vertices[i][TX] < nwidth2) ||
 
246
            (vertices[i][TX] > width2) ||
 
247
            (vertices[i][TY] < nheight2) ||
 
248
            (vertices[i][TY] > height2)) {
 
249
          return;  // this is a bad poly
 
250
        }
 
251
      }
 
252
    }
 
253
    */
 
254
 
 
255
//    for (int i = 0; i < 4; i++) {
 
256
//      System.out.println(vertices[i][R] + " " + vertices[i][G] + " " + vertices[i][B]);
 
257
//    }
 
258
//    System.out.println();
 
259
    
 
260
    if (smooth) {
 
261
      for (int i = 0; i < vertexCount; i++) {
 
262
        vertices[i][TX] *= SUBXRES;
 
263
        vertices[i][TY] *= SUBYRES;
 
264
      }
 
265
      firstModY = -1;
 
266
    }
 
267
 
 
268
    // find top vertex (y is zero at top, higher downwards)
 
269
    int topi = 0;
 
270
    float ymin = vertices[0][TY];
 
271
    float ymax = vertices[0][TY]; // fry 031001
 
272
    for (int i = 1; i < vertexCount; i++) {
 
273
      if (vertices[i][TY] < ymin) {
 
274
        ymin = vertices[i][TY];
 
275
        topi = i;
 
276
      }
 
277
      if (vertices[i][TY] > ymax) {
 
278
        ymax = vertices[i][TY];
 
279
      }
 
280
    }
 
281
 
 
282
    // the last row is an exceptional case, because there won't
 
283
    // necessarily be 8 rows of subpixel lines that will force
 
284
    // the final line to render. so instead, the algo keeps track
 
285
    // of the lastY (in subpixel resolution) that will be rendered
 
286
    // and that will force a scanline to happen the same as
 
287
    // every eighth in the other situations
 
288
    //lastY = -1;  // fry 031001
 
289
    lastY = (int) (ymax - 0.5f);  // global to class bc used by other fxns
 
290
 
 
291
    int lefti = topi;             // li, index of left vertex
 
292
    int righti = topi;            // ri, index of right vertex
 
293
    int y = (int) (ymin + 0.5f);  // current scan line
 
294
    int lefty = y - 1;            // lower end of left edge
 
295
    int righty = y - 1;           // lower end of right edge
 
296
 
 
297
    interpX = true;
 
298
 
 
299
    int remaining = vertexCount;
 
300
 
 
301
    // scan in y, activating new edges on left & right
 
302
    // as scan line passes over new vertices
 
303
    while (remaining > 0) {
 
304
      // advance left edge?
 
305
      while ((lefty <= y) && (remaining > 0)) {
 
306
        remaining--;
 
307
        // step ccw down left side
 
308
        int i = (lefti != 0) ? (lefti-1) : (vertexCount-1);
 
309
        incrementalizeY(vertices[lefti], vertices[i], l, dl, y);
 
310
        lefty = (int) (vertices[i][TY] + 0.5f);
 
311
        lefti = i;
 
312
      }
 
313
 
 
314
      // advance right edge?
 
315
      while ((righty <= y) && (remaining > 0)) {
 
316
        remaining--;
 
317
        // step cw down right edge
 
318
        int i = (righti != vertexCount-1) ? (righti + 1) : 0;
 
319
        incrementalizeY(vertices[righti], vertices[i], r, dr, y);
 
320
        righty = (int) (vertices[i][TY] + 0.5f);
 
321
        righti = i;
 
322
      }
 
323
 
 
324
      // do scanlines till end of l or r edge
 
325
      while (y < lefty && y < righty) {
 
326
        // this doesn't work because it's not always set here
 
327
        //if (remaining == 0) {
 
328
        //lastY = (lefty < righty) ? lefty-1 : righty-1;
 
329
        //System.out.println("lastY is " + lastY);
 
330
        //}
 
331
 
 
332
        if ((y >= 0) && (y < height)) {
 
333
          //try {  // hopefully this bug is fixed
 
334
          if (l[TX] <= r[TX]) scanline(y, l, r);
 
335
          else scanline(y, r, l);
 
336
          //} catch (ArrayIndexOutOfBoundsException e) {
 
337
          //e.printStackTrace();
 
338
          //}
 
339
        }
 
340
        y++;
 
341
        // this increment probably needs to be different
 
342
        // UV and RGB shouldn't be incremented until line is emitted
 
343
        increment(l, dl);
 
344
        increment(r, dr);
 
345
      }
 
346
    }
 
347
    //if (smooth) {
 
348
    //System.out.println("y/lasty/lastmody = " + y + " " + lastY + " " + lastModY);
 
349
    //}
 
350
  }
 
351
 
 
352
 
 
353
  private void scanline(int y, float l[], float r[]) {
 
354
    //System.out.println("scanline " + y);
 
355
    for (int i = 0; i < vertexCount; i++) {  // should be moved later
 
356
      sp[i] = 0; sdp[i] = 0;
 
357
    }
 
358
 
 
359
    // this rounding doesn't seem to be relevant with smooth
 
360
    int lx = (int) (l[TX] + 0.49999f);  // ceil(l[TX]-.5);
 
361
    if (lx < 0) lx = 0;
 
362
    int rx = (int) (r[TX] - 0.5f);
 
363
    if (rx > width1) rx = width1;
 
364
 
 
365
    if (lx > rx) return;
 
366
 
 
367
    if (smooth) {
 
368
      int mody = MODYRES(y);
 
369
 
 
370
      aaleft[mody] = lx;
 
371
      aaright[mody] = rx;
 
372
 
 
373
      if (firstModY == -1) {
 
374
        firstModY = mody;
 
375
        aaleftmin = lx; aaleftmax = lx;
 
376
        aarightmin = rx; aarightmax = rx;
 
377
 
 
378
      } else {
 
379
        if (aaleftmin > aaleft[mody]) aaleftmin = aaleft[mody];
 
380
        if (aaleftmax < aaleft[mody]) aaleftmax = aaleft[mody];
 
381
        if (aarightmin > aaright[mody]) aarightmin = aaright[mody];
 
382
        if (aarightmax < aaright[mody]) aarightmax = aaright[mody];
 
383
      }
 
384
 
 
385
      lastModY = mody;  // moved up here (before the return) 031001
 
386
      // not the eighth (or lastY) line, so not scanning this time
 
387
      if ((mody != SUBYRES1) && (y != lastY)) return;
 
388
        //lastModY = mody;  // eeK! this was missing
 
389
      //return;
 
390
 
 
391
      //if (y == lastY) {
 
392
      //System.out.println("y is lasty");
 
393
      //}
 
394
      //lastModY = mody;
 
395
      aaleftfull = aaleftmax/SUBXRES + 1;
 
396
      aarightfull = aarightmin/SUBXRES - 1;
 
397
    }
 
398
 
 
399
    // this is the setup, based on lx
 
400
    incrementalizeX(l, r, sp, sdp, lx);
 
401
 
 
402
    // scan in x, generating pixels
 
403
    // using parent.width to get actual pixel index
 
404
    // rather than scaled by smooth factor
 
405
    int offset = smooth ? parent.width * (y / SUBYRES) : parent.width*y;
 
406
 
 
407
    int truelx = 0, truerx = 0;
 
408
    if (smooth) {
 
409
      truelx = lx / SUBXRES;
 
410
      truerx = (rx + SUBXRES1) / SUBXRES;
 
411
 
 
412
      lx = aaleftmin / SUBXRES;
 
413
      rx = (aarightmax + SUBXRES1) / SUBXRES;
 
414
      if (lx < 0) lx = 0;
 
415
      if (rx > parent.width1) rx = parent.width1;
 
416
    }
 
417
 
 
418
    interpX = false;
 
419
    int tr, tg, tb, ta;
 
420
 
 
421
//    System.out.println("P2D interp uv " + interpUV + " " + 
 
422
//                       vertices[2][U] + " " + vertices[2][V]);    
 
423
    for (int x = lx; x <= rx; x++) {
 
424
      // map texture based on U, V coords in sp[U] and sp[V]
 
425
      if (interpUV) {
 
426
        int tu = (int) (sp[U] * twidth);
 
427
        int tv = (int) (sp[V] * theight);
 
428
 
 
429
        if (tu > twidth1) tu = twidth1;
 
430
        if (tv > theight1) tv = theight1;
 
431
        if (tu < 0) tu = 0;
 
432
        if (tv < 0) tv = 0;
 
433
 
 
434
        int txy = tv*twidth + tu;
 
435
 
 
436
        int tuf1 = (int) (255f * (sp[U]*twidth - (float)tu));
 
437
        int tvf1 = (int) (255f * (sp[V]*theight - (float)tv));
 
438
 
 
439
        // the closer sp[U or V] is to the decimal being zero
 
440
        // the more coverage it should get of the original pixel
 
441
        int tuf = 255 - tuf1;
 
442
        int tvf = 255 - tvf1;
 
443
 
 
444
        // this code sucks! filled with bugs and slow as hell!
 
445
        int pixel00 = tpixels[txy];
 
446
        int pixel01 = (tv < theight1) ?
 
447
          tpixels[txy + twidth] : tpixels[txy];
 
448
        int pixel10 = (tu < twidth1) ?
 
449
          tpixels[txy + 1] : tpixels[txy];
 
450
        int pixel11 = ((tv < theight1) && (tu < twidth1)) ?
 
451
          tpixels[txy + twidth + 1] : tpixels[txy];
 
452
 
 
453
        int p00, p01, p10, p11;
 
454
        int px0, px1; //, pxy;
 
455
 
 
456
        
 
457
        // calculate alpha component (ta)
 
458
        
 
459
        if (tformat == ALPHA) {
 
460
          px0 = (pixel00*tuf + pixel10*tuf1) >> 8;
 
461
          px1 = (pixel01*tuf + pixel11*tuf1) >> 8;
 
462
          ta = (((px0*tvf + px1*tvf1) >> 8) *
 
463
            (interpARGB ? ((int) (sp[A]*255)) : a2orig)) >> 8;
 
464
 
 
465
        } else if (tformat == ARGB) {
 
466
          p00 = (pixel00 >> 24) & 0xff;
 
467
          p01 = (pixel01 >> 24) & 0xff;
 
468
          p10 = (pixel10 >> 24) & 0xff;
 
469
          p11 = (pixel11 >> 24) & 0xff;
 
470
 
 
471
          px0 = (p00*tuf + p10*tuf1) >> 8;
 
472
          px1 = (p01*tuf + p11*tuf1) >> 8;
 
473
          ta = (((px0*tvf + px1*tvf1) >> 8) *
 
474
                (interpARGB ? ((int) (sp[A]*255)) : a2orig)) >> 8;
 
475
 
 
476
        } else {  // RGB image, no alpha
 
477
          ta = interpARGB ? ((int) (sp[A]*255)) : a2orig;
 
478
        }
 
479
 
 
480
        // calculate r,g,b components (tr, tg, tb)
 
481
        
 
482
        if ((tformat == RGB) || (tformat == ARGB)) {
 
483
          p00 = (pixel00 >> 16) & 0xff;  // red
 
484
          p01 = (pixel01 >> 16) & 0xff;
 
485
          p10 = (pixel10 >> 16) & 0xff;
 
486
          p11 = (pixel11 >> 16) & 0xff;
 
487
 
 
488
          px0 = (p00*tuf + p10*tuf1) >> 8;
 
489
          px1 = (p01*tuf + p11*tuf1) >> 8;
 
490
          tr = (((px0*tvf + px1*tvf1) >> 8) *
 
491
                (interpARGB ? ((int) (sp[R]*255)) : r2)) >> 8;
 
492
                
 
493
          p00 = (pixel00 >> 8) & 0xff;  // green
 
494
          p01 = (pixel01 >> 8) & 0xff;
 
495
          p10 = (pixel10 >> 8) & 0xff;
 
496
          p11 = (pixel11 >> 8) & 0xff;
 
497
 
 
498
          px0 = (p00*tuf + p10*tuf1) >> 8;
 
499
          px1 = (p01*tuf + p11*tuf1) >> 8;
 
500
          tg = (((px0*tvf + px1*tvf1) >> 8) *
 
501
                (interpARGB ? ((int) (sp[G]*255)) : g2)) >> 8;
 
502
 
 
503
          p00 = pixel00 & 0xff;  // blue
 
504
          p01 = pixel01 & 0xff;
 
505
          p10 = pixel10 & 0xff;
 
506
          p11 = pixel11 & 0xff;
 
507
 
 
508
          px0 = (p00*tuf + p10*tuf1) >> 8;
 
509
          px1 = (p01*tuf + p11*tuf1) >> 8;
 
510
          tb = (((px0*tvf + px1*tvf1) >> 8) *
 
511
                (interpARGB ? ((int) (sp[B]*255)) : b2)) >> 8;
 
512
 
 
513
        } else {  // alpha image, only use current fill color
 
514
          if (interpARGB) {
 
515
            tr = (int) (sp[R] * 255);
 
516
            tg = (int) (sp[G] * 255);
 
517
            tb = (int) (sp[B] * 255);
 
518
 
 
519
          } else {
 
520
            tr = r2;
 
521
            tg = g2;
 
522
            tb = b2;
 
523
          }
 
524
        }
 
525
 
 
526
        int weight = smooth ? coverage(x) : 255;
 
527
        if (weight != 255) ta = ta*weight >> 8;
 
528
        
 
529
        if ((ta == 254) || (ta == 255)) {  // if (ta & 0xf8) would be good
 
530
          // no need to blend
 
531
          pixels[offset+x] = 0xff000000 | (tr << 16) | (tg << 8) | tb;
 
532
 
 
533
        } else {
 
534
          // blend with pixel on screen
 
535
          int a1 = 255-ta;
 
536
          int r1 = (pixels[offset+x] >> 16) & 0xff;
 
537
          int g1 = (pixels[offset+x] >> 8) & 0xff;
 
538
          int b1 = (pixels[offset+x]) & 0xff;
 
539
 
 
540
          pixels[offset+x] = 0xff000000 |
 
541
            (((tr*ta + r1*a1) >> 8) << 16) |
 
542
            ((tg*ta + g1*a1) & 0xff00) |
 
543
            ((tb*ta + b1*a1) >> 8);
 
544
        }
 
545
 
 
546
      } else {  // no image applied
 
547
        int weight = smooth ? coverage(x) : 255;
 
548
 
 
549
        if (interpARGB) {
 
550
          r2 = (int) (sp[R] * 255);
 
551
          g2 = (int) (sp[G] * 255);
 
552
          b2 = (int) (sp[B] * 255);
 
553
          if (sp[A] != 1) weight = (weight * ((int) (sp[A] * 255))) >> 8;
 
554
          if (weight == 255) {
 
555
            rgba = 0xff000000 | (r2 << 16) | (g2 << 8) | b2;
 
556
          }
 
557
        } else {
 
558
          if (a2orig != 255) weight = (weight * a2orig) >> 8;
 
559
        }
 
560
 
 
561
        if (weight == 255) {
 
562
          // no blend, no aa, just the rgba
 
563
          pixels[offset+x] = rgba;
 
564
          //zbuffer[offset+x] = sp[Z];
 
565
 
 
566
        } else {
 
567
          int r1 = (pixels[offset+x] >> 16) & 0xff;
 
568
          int g1 = (pixels[offset+x] >> 8) & 0xff;
 
569
          int b1 = (pixels[offset+x]) & 0xff;
 
570
          a2 = weight;
 
571
 
 
572
          int a1 = 255 - a2;
 
573
          pixels[offset+x] = (0xff000000 |
 
574
                              ((r1*a1 + r2*a2) >> 8) << 16 |
 
575
                              // use & instead of >> and << below
 
576
                              ((g1*a1 + g2*a2) >> 8) << 8 |
 
577
                              ((b1*a1 + b2*a2) >> 8));
 
578
        }
 
579
      }
 
580
 
 
581
      // if smooth enabled, don't increment values
 
582
      // for the pixel in the stretch out version
 
583
      // of the scanline used to get smooth edges.
 
584
      if (!smooth || ((x >= truelx) && (x <= truerx))) {
 
585
        increment(sp, sdp);
 
586
      }
 
587
    }
 
588
    firstModY = -1;
 
589
    interpX = true;
 
590
  }
 
591
 
 
592
 
 
593
  // x is in screen, not huge 8x coordinates
 
594
  private int coverage(int x) {
 
595
    if ((x >= aaleftfull) && (x <= aarightfull) &&
 
596
      // important since not all SUBYRES lines may have been covered
 
597
      (firstModY == 0) && (lastModY == SUBYRES1)) {
 
598
      return 255;
 
599
    }
 
600
 
 
601
    int pixelLeft = x*SUBXRES;  // huh?
 
602
    int pixelRight = pixelLeft + 8;
 
603
 
 
604
    int amt = 0;
 
605
    for (int i = firstModY; i <= lastModY; i++) {
 
606
      if ((aaleft[i] > pixelRight) || (aaright[i] < pixelLeft)) {
 
607
        continue;
 
608
      }
 
609
      // does this need a +1 ?
 
610
      amt += ((aaright[i] < pixelRight ? aaright[i] : pixelRight) -
 
611
              (aaleft[i] > pixelLeft ? aaleft[i] : pixelLeft));
 
612
    }
 
613
    amt <<= 2;
 
614
    return (amt == 256) ? 255 : amt;
 
615
  }
 
616
 
 
617
 
 
618
  private void incrementalizeY(float p1[], float p2[],
 
619
                               float p[], float dp[], int y) {
 
620
    float delta = p2[TY] - p1[TY];
 
621
    if (delta == 0) delta = 1;
 
622
    float fraction = y + 0.5f - p1[TY];
 
623
 
 
624
    if (interpX) {
 
625
      dp[TX] = (p2[TX] - p1[TX]) / delta;
 
626
      p[TX] = p1[TX] + dp[TX] * fraction;
 
627
    }
 
628
 
 
629
    if (interpARGB) {
 
630
      dp[R] = (p2[R] - p1[R]) / delta;
 
631
      dp[G] = (p2[G] - p1[G]) / delta;
 
632
      dp[B] = (p2[B] - p1[B]) / delta;
 
633
      dp[A] = (p2[A] - p1[A]) / delta;
 
634
      p[R] = p1[R] + dp[R] * fraction;
 
635
      p[G] = p1[G] + dp[G] * fraction;
 
636
      p[B] = p1[B] + dp[B] * fraction;
 
637
      p[A] = p1[A] + dp[A] * fraction;
 
638
    }
 
639
 
 
640
    if (interpUV) {
 
641
      dp[U] = (p2[U] - p1[U]) / delta;
 
642
      dp[V] = (p2[V] - p1[V]) / delta;
 
643
 
 
644
      p[U] = p1[U] + dp[U] * fraction;
 
645
      p[V] = p1[V] + dp[V] * fraction;
 
646
    }
 
647
  }
 
648
 
 
649
 
 
650
  private void incrementalizeX(float p1[], float p2[],
 
651
                               float p[], float dp[], int x) {
 
652
    float delta = p2[TX] - p1[TX];
 
653
    if (delta == 0) delta = 1;
 
654
    float fraction = x + 0.5f - p1[TX];
 
655
    if (smooth) {
 
656
      delta /= SUBXRES;
 
657
      fraction /= SUBXRES;
 
658
    }
 
659
 
 
660
    if (interpX) {
 
661
      dp[TX] = (p2[TX] - p1[TX]) / delta;
 
662
      p[TX] = p1[TX] + dp[TX] * fraction;
 
663
    }
 
664
 
 
665
    if (interpARGB) {
 
666
      dp[R] = (p2[R] - p1[R]) / delta;
 
667
      dp[G] = (p2[G] - p1[G]) / delta;
 
668
      dp[B] = (p2[B] - p1[B]) / delta;
 
669
      dp[A] = (p2[A] - p1[A]) / delta;
 
670
      p[R] = p1[R] + dp[R] * fraction;
 
671
      p[G] = p1[G] + dp[G] * fraction;
 
672
      p[B] = p1[B] + dp[B] * fraction;
 
673
      p[A] = p1[A] + dp[A] * fraction;
 
674
    }
 
675
 
 
676
    if (interpUV) {
 
677
      dp[U] = (p2[U] - p1[U]) / delta;
 
678
      dp[V] = (p2[V] - p1[V]) / delta;
 
679
 
 
680
      p[U] = p1[U] + dp[U] * fraction;
 
681
      p[V] = p1[V] + dp[V] * fraction;
 
682
    }
 
683
  }
 
684
 
 
685
 
 
686
  private void increment(float p[], float dp[]) {
 
687
    if (interpX) p[TX] += dp[TX];
 
688
 
 
689
    if (interpARGB) {
 
690
      p[R] += dp[R];
 
691
      p[G] += dp[G];
 
692
      p[B] += dp[B];
 
693
      p[A] += dp[A];
 
694
    }
 
695
 
 
696
    if (interpUV) {
 
697
      p[U] += dp[U];
 
698
      p[V] += dp[V];
 
699
    }
 
700
  }
 
701
}