-#ifdef Q_WS_WIN
-
-
-#endif
-
-
-/*!
- \internal
-
- Draws a line using the floating point midpoint algorithm. The line
- \a line is already in device coords at this point.
-*/
-
-static void drawLine_midpoint_i(int x1, int y1, int x2, int y2, ProcessSpans span_func, QSpanData *data,
- LineDrawMode style, const QIntRect &devRect)
-{
-#ifdef QT_DEBUG_DRAW
- qDebug() << " - drawLine_midpoint_i" << QLine(QPoint(x1, y1), QPoint(x2, y2));
-#endif
-
- int x, y;
- int dx, dy, d, incrE, incrNE;
-
- dx = x2 - x1;
- dy = y2 - y1;
-
- const int NSPANS = 256;
- QT_FT_Span spans[NSPANS];
- int current = 0;
- bool ordered = true;
-
- if (dy == 0) {
- // specialcase horizontal lines
- if (y1 >= devRect.y1 && y1 < devRect.y2) {
- int start = qMax(devRect.x1, qMin(x1, x2));
- int stop = qMax(x1, x2) + 1;
- int stop_clipped = qMin(devRect.x2, stop);
- int len = stop_clipped - start;
- if (style == LineDrawNormal && stop == stop_clipped)
- len--;
- if (len > 0) {
- spans[0].x = ushort(start);
- spans[0].len = ushort(len);
- spans[0].y = y1;
- spans[0].coverage = 255;
- span_func(1, spans, data);
- }
- }
- return;
- } else if (dx == 0) {
- // specialcase vertical lines
- if (x1 >= devRect.x1 && x1 < devRect.x2) {
- int start = qMax(devRect.y1, qMin(y1, y2));
- int stop = qMax(y1, y2) + 1;
- int stop_clipped = qMin(devRect.y2, stop);
- int len = stop_clipped - start;
- if (style == LineDrawNormal && stop == stop_clipped)
- len--;
- // hw: create spans directly instead to possibly avoid clipping
- if (len > 0)
- fillRect_normalized(QRect(x1, start, 1, len).normalized(), data, 0);
- }
- return;
- }
-
-
- if (qAbs(dx) >= qAbs(dy)) { /* if x is the major axis: */
-
- if (x2 < x1) { /* if coordinates are out of order */
- qt_swap_int(x1, x2);
- dx = -dx;
-
- qt_swap_int(y1, y2);
- dy = -dy;
- }
-
- int x_lower_limit = - 128;
- if (x1 < x_lower_limit) {
- int cy = dy * (x_lower_limit - x1) / dx + y1;
- drawLine_midpoint_i(x_lower_limit, cy, x2, y2, span_func, data, style, devRect);
- return;
- }
-
- if (style == LineDrawNormal)
- --x2;
-
- // In the loops below we increment before call the span function so
- // we need to stop one pixel before
- x2 = qMin(x2, devRect.x2 - 1);
-
- // completely clipped, so abort
- if (x2 <= x1) {
- return;
- }
-
- int x = x1;
- int y = y1;
-
- if (y2 <= y1)
- ordered = false;
-
- {
- const int index = (ordered ? current : NSPANS - 1 - current);
- spans[index].coverage = 255;
- spans[index].x = x;
- spans[index].y = y;
-
- if (x >= devRect.x1 && y >= devRect.y1 && y < devRect.y2)
- spans[index].len = 1;
- else
- spans[index].len = 0;
- }
-
- if (y2 > y1) { // 315 -> 360 and 135 -> 180 (unit circle degrees)
- y2 = qMin(y2, devRect.y2 - 1);
-
- incrE = dy * 2;
- d = incrE - dx;
- incrNE = (dy - dx) * 2;
-
- if (y > y2)
- goto flush_and_return;
-
- while (x < x2) {
- ++x;
- if (d > 0) {
- if (spans[current].len > 0)
- ++current;
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
-
- ++y;
- d += incrNE;
- if (y > y2)
- goto flush_and_return;
-
- spans[current].len = 0;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- } else {
- d += incrE;
- if (x == devRect.x1)
- spans[current].x = devRect.x1;
- }
-
- if (x < devRect.x1 || y < devRect.y1)
- continue;
-
- Q_ASSERT(x<devRect.x2);
- Q_ASSERT(y<devRect.y2);
- Q_ASSERT(spans[current].y == y);
- spans[current].len++;
- }
- if (spans[current].len > 0) {
- ++current;
- }
- } else { // 0-45 and 180->225 (unit circle degrees)
-
- y1 = qMin(y1, devRect.y2 - 1);
-
- incrE = dy * 2;
- d = incrE + dx;
- incrNE = (dy + dx) * 2;
-
- if (y < devRect.y1)
- goto flush_and_return;
-
- while (x < x2) {
- ++x;
- if (d < 0) {
- if (spans[NSPANS - 1 - current].len > 0)
- ++current;
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
-
- --y;
- d += incrNE;
- if (y < devRect.y1)
- goto flush_and_return;
-
- const int index = NSPANS - 1 - current;
- spans[index].len = 0;
- spans[index].coverage = 255;
- spans[index].x = x;
- spans[index].y = y;
- } else {
- d += incrE;
- if (x == devRect.x1)
- spans[NSPANS - 1 - current].x = devRect.x1;
- }
-
- if (x < devRect.x1 || y > y1)
- continue;
-
- Q_ASSERT(x<devRect.x2 && y<devRect.y2);
- Q_ASSERT(spans[NSPANS - 1 - current].y == y);
- spans[NSPANS - 1 - current].len++;
- }
- if (spans[NSPANS - 1 - current].len > 0) {
- ++current;
- }
- }
-
- } else {
-
- // if y is the major axis:
-
- if (y2 < y1) { /* if coordinates are out of order */
- qt_swap_int(y1, y2);
- dy = -dy;
-
- qt_swap_int(x1, x2);
- dx = -dx;
- }
-
- int y_lower_limit = - 128;
- if (y1 < y_lower_limit) {
- int cx = dx * (y_lower_limit - y1) / dy + x1;
- drawLine_midpoint_i(cx, y_lower_limit, x2, y2, span_func, data, style, devRect);
- return;
- }
-
- if (style == LineDrawNormal)
- --y2;
-
- // In the loops below we increment before call the span function so
- // we need to stop one pixel before
- y2 = qMin(y2, devRect.y2 - 1);
-
- // completely clipped, so abort
- if (y2 <= y1) {
- return;
- }
-
- x = x1;
- y = y1;
-
- if (x>=devRect.x1 && y>=devRect.y1 && x < devRect.x2) {
- Q_ASSERT(x >= devRect.x1 && y >= devRect.y1 && x < devRect.x2 && y < devRect.y2);
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
-
- if (x2 > x1) { // 90 -> 135 and 270 -> 315 (unit circle degrees)
- x2 = qMin(x2, devRect.x2 - 1);
- incrE = dx * 2;
- d = incrE - dy;
- incrNE = (dx - dy) * 2;
-
- if (x > x2)
- goto flush_and_return;
-
- while (y < y2) {
- if (d > 0) {
- ++x;
- d += incrNE;
- if (x > x2)
- goto flush_and_return;
- } else {
- d += incrE;
- }
- ++y;
- if (x < devRect.x1 || y < devRect.y1)
- continue;
- Q_ASSERT(x<devRect.x2 && y<devRect.y2);
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
- } else { // 45 -> 90 and 225 -> 270 (unit circle degrees)
- x1 = qMin(x1, devRect.x2 - 1);
- incrE = dx * 2;
- d = incrE + dy;
- incrNE = (dx + dy) * 2;
-
- if (x < devRect.x1)
- goto flush_and_return;
-
- while (y < y2) {
- if (d < 0) {
- --x;
- d += incrNE;
- if (x < devRect.x1)
- goto flush_and_return;
- } else {
- d += incrE;
- }
- ++y;
- if (y < devRect.y1 || x > x1)
- continue;
- Q_ASSERT(x>=devRect.x1 && x<devRect.x2 && y>=devRect.y1 && y<devRect.y2);
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
- }
- }
-flush_and_return:
- if (current > 0)
- span_func(current, ordered ? spans : spans + (NSPANS - current), data);
-}
-
-static void offset_pattern(int offset, bool *inDash, int *dashIndex, int *currentOffset, const QVarLengthArray<qreal> &pattern)
-{
- while (offset--) {
- if (--*currentOffset == 0) {
- *inDash = !*inDash;
- *dashIndex = ((*dashIndex + 1) % pattern.size());
- *currentOffset = int(pattern[*dashIndex]);
- }
- }
-}
-
-static void drawLine_midpoint_dashed_i(int x1, int y1, int x2, int y2,
- QPen *pen,
- ProcessSpans span_func, QSpanData *data,
- LineDrawMode style, const QIntRect &devRect,
- int *patternOffset)
-{
-#ifdef QT_DEBUG_DRAW
- qDebug() << " - drawLine_midpoint_dashed_i" << x1 << y1 << x2 << y2 << *patternOffset;
-#endif
-
- int x, y;
- int dx, dy, d, incrE, incrNE;
-
- dx = x2 - x1;
- dy = y2 - y1;
-
- Q_ASSERT(*patternOffset >= 0);
-
- const QVector<qreal> penPattern = pen->dashPattern();
- QVarLengthArray<qreal> pattern(penPattern.size());
-
- int patternLength = 0;
- for (int i = 0; i < penPattern.size(); ++i)
- patternLength += qMax<qreal>(1.0, (penPattern.at(i)));
-
- // pattern must be reversed if coordinates are out of order
- int reverseLength = -1;
- if (dy == 0 && x1 > x2)
- reverseLength = x1 - x2;
- else if (dx == 0 && y1 > y2)
- reverseLength = y1 - y2;
- else if (qAbs(dx) >= qAbs(dy) && x2 < x1) // x major axis
- reverseLength = qAbs(dx);
- else if (qAbs(dy) >= qAbs(dx) && y2 < y1) // y major axis
- reverseLength = qAbs(dy);
-
- const bool reversed = (reverseLength > -1);
- if (reversed) { // reverse pattern
- for (int i = 0; i < penPattern.size(); ++i)
- pattern[penPattern.size() - 1 - i] = qMax<qreal>(1.0, penPattern.at(i));
-
- *patternOffset = (patternLength - 1 - *patternOffset);
- *patternOffset += patternLength - (reverseLength % patternLength);
- *patternOffset = *patternOffset % patternLength;
- } else {
- for (int i = 0; i < penPattern.size(); ++i)
- pattern[i] = qMax<qreal>(1.0, penPattern.at(i));
- }
-
- int dashIndex = 0;
- bool inDash = !reversed;
- int currPattern = int(pattern[dashIndex]);
-
- // adjust pattern for offset
- offset_pattern(*patternOffset, &inDash, &dashIndex, &currPattern, pattern);
-
- const int NSPANS = 256;
- QT_FT_Span spans[NSPANS];
- int current = 0;
- bool ordered = true;
-
- if (dy == 0) {
- // specialcase horizontal lines
- if (y1 >= devRect.y1 && y1 < devRect.y2) {
- int start_unclipped = qMin(x1, x2);
- int start = qMax(devRect.x1, start_unclipped);
- int stop = qMax(x1, x2) + 1;
- int stop_clipped = qMin(devRect.x2, stop);
- int len = stop_clipped - start;
- if (style == LineDrawNormal && stop == stop_clipped)
- len--;
-
- // adjust pattern for starting offset
- offset_pattern(start - start_unclipped, &inDash, &dashIndex, &currPattern, pattern);
-
- if (len > 0) {
- int x = start;
- while (x < stop_clipped) {
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- const int dash = qMin(currPattern, stop_clipped - x);
- if (inDash) {
- spans[current].x = ushort(x);
- spans[current].len = ushort(dash);
- spans[current].y = y1;
- spans[current].coverage = 255;
- ++current;
- }
- if (dash < currPattern) {
- currPattern -= dash;
- } else {
- dashIndex = (dashIndex + 1) % pattern.size();
- currPattern = int(pattern[dashIndex]);
- inDash = !inDash;
- }
- x += dash;
- }
- }
- }
- goto flush_and_return;
- } else if (dx == 0) {
- if (x1 >= devRect.x1 && x1 < devRect.x2) {
- int start_unclipped = qMin(y1, y2);
- int start = qMax(devRect.y1, start_unclipped);
- int stop = qMax(y1, y2) + 1;
- int stop_clipped = qMin(devRect.y2, stop);
- if (style == LineDrawNormal && stop == stop_clipped)
- --stop;
- else
- stop = stop_clipped;
-
- // adjust pattern for starting offset
- offset_pattern(start - start_unclipped, &inDash, &dashIndex, &currPattern, pattern);
-
- // loop over dashes
- int y = start;
- while (y < stop) {
- const int dash = qMin(currPattern, stop - y);
- if (inDash) {
- for (int i = 0; i < dash; ++i) {
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].x = x1;
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].y = ushort(y + i);
- ++current;
- }
- }
- if (dash < currPattern) {
- currPattern -= dash;
- } else {
- dashIndex = (dashIndex + 1) % pattern.size();
- currPattern = int(pattern[dashIndex]);
- inDash = !inDash;
- }
- y += dash;
- }
- }
- goto flush_and_return;
- }
-
- if (qAbs(dx) >= qAbs(dy)) { /* if x is the major axis: */
-
- if (x2 < x1) { /* if coordinates are out of order */
- qt_swap_int(x1, x2);
- dx = -dx;
-
- qt_swap_int(y1, y2);
- dy = -dy;
- }
-
- if (style == LineDrawNormal)
- --x2;
-
- // In the loops below we increment before call the span function so
- // we need to stop one pixel before
- x2 = qMin(x2, devRect.x2 - 1);
-
- // completely clipped, so abort
- if (x2 <= x1)
- goto flush_and_return;
-
- int x = x1;
- int y = y1;
-
- if (x >= devRect.x1 && y >= devRect.y1 && y < devRect.y2) {
- Q_ASSERT(x < devRect.x2);
- if (inDash) {
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
- if (--currPattern <= 0) {
- inDash = !inDash;
- dashIndex = (dashIndex + 1) % pattern.size();
- currPattern = int(pattern[dashIndex]);
- }
- }
-
- if (y2 > y1) { // 315 -> 360 and 135 -> 180 (unit circle degrees)
- y2 = qMin(y2, devRect.y2 - 1);
-
- incrE = dy * 2;
- d = incrE - dx;
- incrNE = (dy - dx) * 2;
-
- if (y > y2)
- goto flush_and_return;
-
- while (x < x2) {
- if (d > 0) {
- ++y;
- d += incrNE;
- if (y > y2)
- goto flush_and_return;
- } else {
- d += incrE;
- }
- ++x;
-
- const bool skip = x < devRect.x1 || y < devRect.y1;
- Q_ASSERT(skip || (x < devRect.x2 && y < devRect.y2));
- if (inDash && !skip) {
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
- if (--currPattern <= 0) {
- inDash = !inDash;
- dashIndex = (dashIndex + 1) % pattern.size();
- currPattern = int(pattern[dashIndex]);
- }
- }
- } else { // 0-45 and 180->225 (unit circle degrees)
- y1 = qMin(y1, devRect.y2 - 1);
-
- incrE = dy * 2;
- d = incrE + dx;
- incrNE = (dy + dx) * 2;
-
- if (y < devRect.y1)
- goto flush_and_return;
-
- while (x < x2) {
- if (d < 0) {
- if (current > 0) {
- span_func(current, spans, data);
- current = 0;
- }
-
- --y;
- d += incrNE;
- if (y < devRect.y1)
- goto flush_and_return;
- } else {
- d += incrE;
- }
- ++x;
-
- const bool skip = x < devRect.x1 || y > y1;
- Q_ASSERT(skip || (x < devRect.x2 && y < devRect.y2));
- if (inDash && !skip) {
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
- if (--currPattern <= 0) {
- inDash = !inDash;
- dashIndex = (dashIndex + 1) % pattern.size();
- currPattern = int(pattern[dashIndex]);
- }
- }
- }
- } else {
-
- // if y is the major axis:
-
- if (y2 < y1) { /* if coordinates are out of order */
- qt_swap_int(y1, y2);
- dy = -dy;
-
- qt_swap_int(x1, x2);
- dx = -dx;
- }
-
- if (style == LineDrawNormal)
- --y2;
-
- // In the loops below we increment before call the span function so
- // we need to stop one pixel before
- y2 = qMin(y2, devRect.y2 - 1);
-
- // completely clipped, so abort
- if (y2 <= y1)
- goto flush_and_return;
-
- x = x1;
- y = y1;
-
- if (x>=devRect.x1 && y>=devRect.y1 && x < devRect.x2) {
- Q_ASSERT(x < devRect.x2);
- if (inDash) {
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
- if (--currPattern <= 0) {
- inDash = !inDash;
- dashIndex = (dashIndex + 1) % pattern.size();
- currPattern = int(pattern[dashIndex]);
- }
- }
-
- if (x2 > x1) { // 90 -> 135 and 270 -> 315 (unit circle degrees)
- x2 = qMin(x2, devRect.x2 - 1);
- incrE = dx * 2;
- d = incrE - dy;
- incrNE = (dx - dy) * 2;
-
- if (x > x2)
- goto flush_and_return;
-
- while (y < y2) {
- if (d > 0) {
- ++x;
- d += incrNE;
- if (x > x2)
- goto flush_and_return;
- } else {
- d += incrE;
- }
- ++y;
- const bool skip = x < devRect.x1 || y < devRect.y1;
- Q_ASSERT(skip || (x < devRect.x2 && y < devRect.y2));
- if (inDash && !skip) {
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
- if (--currPattern <= 0) {
- inDash = !inDash;
- dashIndex = (dashIndex + 1) % pattern.size();
- currPattern = int(pattern[dashIndex]);
- }
- }
- } else { // 45 -> 90 and 225 -> 270 (unit circle degrees)
- x1 = qMin(x1, devRect.x2 - 1);
- incrE = dx * 2;
- d = incrE + dy;
- incrNE = (dx + dy) * 2;
-
- if (x < devRect.x1)
- goto flush_and_return;
-
- while (y < y2) {
- if (d < 0) {
- --x;
- d += incrNE;
- if (x < devRect.x1)
- goto flush_and_return;
- } else {
- d += incrE;
- }
- ++y;
- const bool skip = y < devRect.y1 || x > x1;
- Q_ASSERT(skip || (x >= devRect.x1 && x < devRect.x2 && y < devRect.y2));
- if (inDash && !skip) {
- if (current == NSPANS) {
- span_func(NSPANS, spans, data);
- current = 0;
- }
- spans[current].len = 1;
- spans[current].coverage = 255;
- spans[current].x = x;
- spans[current].y = y;
- ++current;
- }
- if (--currPattern <= 0) {
- inDash = !inDash;
- dashIndex = (dashIndex + 1) % pattern.size();
- currPattern = int(pattern[dashIndex]);
- }
- }
- }
- }
-flush_and_return:
- if (current > 0)
- span_func(current, ordered ? spans : spans + (NSPANS - current), data);
-
- // adjust offset
- if (reversed) {
- *patternOffset = (patternLength - 1 - *patternOffset);
- } else {
- *patternOffset = 0;
- for (int i = 0; i <= dashIndex; ++i)
- *patternOffset += int(pattern[i]);
- *patternOffset += patternLength - currPattern - 1;
- *patternOffset = (*patternOffset % patternLength);
- }
-}
-