gt:                         xsteps -= 1;
context: /*
   * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  /**
   * Bresenham line-drawing implementation decomposing line segments
   * into a series of rectangles.
   * This is required, because xrender doesn't support line primitives directly.
   * The code here is an almost 1:1 port of the existing C-source contained in
   * sun/java2d/loop/DrawLine.c and sun/java2d/loop/LoopMacros.h
   */
  package sun.java2d.xr;
  
  public class XRDrawLine {
      static final int BIG_MAX = ((1 << 29) - 1);
      static final int BIG_MIN = (-(1 << 29));
  
      static final int OUTCODE_TOP = 1;
      static final int OUTCODE_BOTTOM = 2;
      static final int OUTCODE_LEFT = 4;
      static final int OUTCODE_RIGHT = 8;
  
      int x1, y1, x2, y2;
      int ucX1, ucY1, ucX2, ucY2;
  
      DirtyRegion region = new DirtyRegion();
  
      protected void rasterizeLine(GrowableRectArray rectBuffer, int _x1,
              int _y1, int _x2, int _y2, int cxmin, int cymin, int cxmax,
              int cymax, boolean clip, boolean overflowCheck) {
          float diagF;
          int error;
          int steps;
          int errminor, errmajor;
          boolean xmajor;
          int dx, dy, ax, ay;
  
          initCoordinates(_x1, _y1, _x2, _y2, overflowCheck);
  
          dx = x2 - x1;
          dy = y2 - y1;
          ax = Math.abs(dx);
          ay = Math.abs(dy);
          xmajor = (ax >= ay);
          diagF = ((float) ax) / ay;
  
          if (clip
                  && !clipCoordinates(cxmin, cymin, cxmax, cymax, xmajor, dx, dy,
                          ax, ay)) {
              // whole line was clipped away
              return;
          }
  
          region.setDirtyLineRegion(x1, y1, x2, y2);
          int xDiff = region.x2 - region.x;
          int yDiff = region.y2 - region.y;
  
          if (xDiff == 0 || yDiff == 0) {
              // horizontal / diagonal lines can be represented by a single
              // rectangle
              rectBuffer.pushRectValues(region.x, region.y, region.x2 - region.x
                      + 1, region.y2 - region.y + 1);
              return;
          }
  
          // Setup bresenham
          if (xmajor) {
              errmajor = ay * 2;
              errminor = ax * 2;
              ax = -ax; /* For clipping adjustment below */
              steps = x2 - x1;
          } else {
              errmajor = ax * 2;
              errminor = ay * 2;
              ay = -ay; /* For clipping adjustment below */
              steps = y2 - y1;
          }
  
          if ((steps = (Math.abs(steps) + 1)) == 0) {
              return;
          }
  
          error = -(errminor / 2);
  
          if (y1 != ucY1) {
              int ysteps = y1 - ucY1;
              if (ysteps < 0) {
                  ysteps = -ysteps;
              }
              error += ysteps * ax * 2;
          }
  
          if (x1 != ucX1) {
              int xsteps = x1 - ucX1;
              if (xsteps < 0) {
                  xsteps = -xsteps;
              }
              error += xsteps * ay * 2;
          }
          error += errmajor;
          errminor -= errmajor;
  
          int xStep = (dx > 0 ? 1 : -1);
          int yStep = (dy > 0 ? 1 : -1);
          int orthogonalXStep = xmajor ? xStep : 0;
          int orthogonalYStep = !xmajor ? yStep : 0;
  
          /*
           * For lines which proceed in one direction faster, we try to generate
           * rectangles instead of points. Otherwise we try to avoid the extra
           * work...
           */
          if (diagF <= 0.9 || diagF >= 1.1) {
              lineToRects(rectBuffer, steps, error, errmajor, errminor, xStep,
                      yStep, orthogonalXStep, orthogonalYStep);
          } else {
              lineToPoints(rectBuffer, steps, error, errmajor, errminor, xStep,
                      yStep, orthogonalXStep, orthogonalYStep);
          }
      }
  
      private void lineToPoints(GrowableRectArray rectBuffer, int steps,
              int error, int errmajor, int errminor, int xStep, int yStep,
              int orthogonalXStep, int orthogonalYStep) {
          int x = x1, y = y1;
  
          do {
              rectBuffer.pushRectValues(x, y, 1, 1);
  
              // "Traditional" Bresenham line drawing
              if (error < 0) {
                  error += errmajor;
                  x += orthogonalXStep;
                  y += orthogonalYStep;
              } else {
                  error -= errminor;
                  x += xStep;
                  y += yStep;
              }
          } while (--steps > 0);
      }
  
      private void lineToRects(GrowableRectArray rectBuffer, int steps,
              int error, int errmajor, int errminor, int xStep, int yStep,
              int orthogonalXStep, int orthogonalYStep) {
          int x = x1, y = y1;
          int rectX = Integer.MIN_VALUE, rectY = 0;
          int rectW = 0, rectH = 0;
  
          do {
              // Combine the resulting rectangles
              // for steps performed in a single direction.
              if (y == rectY) {
                  if (x == (rectX + rectW)) {
                      rectW++;
                  } else if (x == (rectX - 1)) {
                      rectX--;
                      rectW++;
                  }
              } else if (x == rectX) {
                  if (y == (rectY + rectH)) {
                      rectH++;
                  } else if (y == (rectY - 1)) {
                      rectY--;
                      rectH++;
                  }
              } else {
                  // Diagonal step: add the previous rectangle to the list,
                  // iff it was "real" (= not initialized before the first
                  // iteration)
                  if (rectX != Integer.MIN_VALUE) {
                      rectBuffer.pushRectValues(rectX, rectY, rectW, rectH);
                  }
                  rectX = x;
                  rectY = y;
                  rectW = rectH = 1;
              }
  
              // "Traditional" Bresenham line drawing
              if (error < 0) {
                  error += errmajor;
                  x += orthogonalXStep;
                  y += orthogonalYStep;
              } else {
                  error -= errminor;
                  x += xStep;
                  y += yStep;
              }
          } while (--steps > 0);
  
          // Add last rectangle which isn't handled by the combination-code
          // anymore
          rectBuffer.pushRectValues(rectX, rectY, rectW, rectH);
      }
  
      private boolean clipCoordinates(int cxmin, int cymin, int cxmax, int cymax,
              boolean xmajor, int dx, int dy, int ax, int ay) {
          int outcode1, outcode2;
  
          outcode1 = outcode(x1, y1, cxmin, cymin, cxmax, cymax);
          outcode2 = outcode(x2, y2, cxmin, cymin, cxmax, cymax);
  
          while ((outcode1 | outcode2) != 0) {
              int xsteps = 0, ysteps = 0;
  
              if ((outcode1 & outcode2) != 0) {
                  return false;
              }
  
              if (outcode1 != 0) {
                  if ((outcode1 & (OUTCODE_TOP | OUTCODE_BOTTOM)) != 0) {
                      if ((outcode1 & OUTCODE_TOP) != 0) {
                          y1 = cymin;
                      } else {
                          y1 = cymax;
                      }
                      ysteps = y1 - ucY1;
                      if (ysteps < 0) {
                          ysteps = -ysteps;
                      }
                      xsteps = 2 * ysteps * ax + ay;
                      if (xmajor) {
                          xsteps += ay - ax - 1;
                      }
                      xsteps = xsteps / (2 * ay);
                      if (dx < 0) {
                          xsteps = -xsteps;
                      }
                      x1 = ucX1 + xsteps;
                  } else if ((outcode1 & (OUTCODE_LEFT | OUTCODE_RIGHT)) != 0) {
                      if ((outcode1 & OUTCODE_LEFT) != 0) {
                          x1 = cxmin;
                      } else {
                          x1 = cxmax;
                      }
                      xsteps = x1 - ucX1;
                      if (xsteps < 0) {
                          xsteps = -xsteps;
                      }
                      ysteps = 2 * xsteps * ay + ax;
                      if (!xmajor) {
                          ysteps += ax - ay - 1;
                      }
                      ysteps = ysteps / (2 * ax);
                      if (dy < 0) {
                          ysteps = -ysteps;
                      }
                      y1 = ucY1 + ysteps;
                  }
                  outcode1 = outcode(x1, y1, cxmin, cymin, cxmax, cymax);
              } else {
                  if ((outcode2 & (OUTCODE_TOP | OUTCODE_BOTTOM)) != 0) {
                      if ((outcode2 & OUTCODE_TOP) != 0) {
                          y2 = cymin;
                      } else {
                          y2 = cymax;
                      }
                      ysteps = y2 - ucY2;
                      if (ysteps < 0) {
                          ysteps = -ysteps;
                      }
                      xsteps = 2 * ysteps * ax + ay;
                      if (xmajor) {
                          xsteps += ay - ax;
                      } else {
  