--- old/src/java.desktop/share/classes/sun/java2d/marlin/Dasher.java 2017-11-16 23:47:31.495810291 +0100 +++ new/src/java.desktop/share/classes/sun/java2d/marlin/Dasher.java 2017-11-16 23:47:31.359806177 +0100 @@ -138,7 +138,7 @@ dashOn = !dashOn; } } - } else if (phase > 0) { + } else if (phase > 0.0f) { if (cycles >= MAX_CYCLES) { phase = 0.0f; } else { @@ -158,12 +158,13 @@ this.dash = dash; this.dashLen = dashLen; - this.startPhase = this.phase = phase; + this.phase = phase; + this.startPhase = phase; this.startDashOn = dashOn; this.startIdx = sidx; this.starting = true; - needsMoveTo = false; - firstSegidx = 0; + this.needsMoveTo = false; + this.firstSegidx = 0; this.recycleDashes = recycleDashes; @@ -202,8 +203,8 @@ } @Override - public void moveTo(float x0, float y0) { - if (firstSegidx > 0) { + public void moveTo(final float x0, final float y0) { + if (firstSegidx != 0) { out.moveTo(sx, sy); emitFirstSegments(); } @@ -211,8 +212,10 @@ this.idx = startIdx; this.dashOn = this.startDashOn; this.phase = this.startPhase; - this.sx = this.x0 = x0; - this.sy = this.y0 = y0; + this.sx = x0; + this.sy = y0; + this.x0 = x0; + this.y0 = y0; this.starting = true; } @@ -237,7 +240,7 @@ private void emitFirstSegments() { final float[] fSegBuf = firstSegmentsBuffer; - for (int i = 0; i < firstSegidx; ) { + for (int i = 0, len = firstSegidx; i < len; ) { int type = (int)fSegBuf[i]; emitSeg(fSegBuf, i + 1, type); i += (type - 1); @@ -252,48 +255,59 @@ private int firstSegidx; // precondition: pts must be in relative coordinates (relative to x0,y0) - private void goTo(float[] pts, int off, final int type) { - float x = pts[off + type - 4]; - float y = pts[off + type - 3]; - if (dashOn) { + private void goTo(final float[] pts, final int off, final int type, + final boolean on) + { + final int index = off + type; + final float x = pts[index - 4]; + final float y = pts[index - 3]; + + if (on) { if (starting) { - int len = type - 1; // - 2 + 1 - int segIdx = firstSegidx; - float[] buf = firstSegmentsBuffer; - if (segIdx + len > buf.length) { - if (DO_STATS) { - rdrCtx.stats.stat_array_dasher_firstSegmentsBuffer - .add(segIdx + len); - } - firstSegmentsBuffer = buf - = firstSegmentsBuffer_ref.widenArray(buf, segIdx, - segIdx + len); - } - buf[segIdx++] = type; - len--; - // small arraycopy (2, 4 or 6) but with offset: - System.arraycopy(pts, off, buf, segIdx, len); - segIdx += len; - firstSegidx = segIdx; + goTo_starting(pts, off, type); } else { if (needsMoveTo) { - out.moveTo(x0, y0); needsMoveTo = false; + out.moveTo(x0, y0); } emitSeg(pts, off, type); } } else { - starting = false; + if (starting) { + // low probability test (hotspot) + starting = false; + } needsMoveTo = true; } this.x0 = x; this.y0 = y; } + private void goTo_starting(final float[] pts, final int off, final int type) { + int len = type - 1; // - 2 + 1 + int segIdx = firstSegidx; + float[] buf = firstSegmentsBuffer; + + if (segIdx + len > buf.length) { + if (DO_STATS) { + rdrCtx.stats.stat_array_dasher_firstSegmentsBuffer + .add(segIdx + len); + } + firstSegmentsBuffer = buf + = firstSegmentsBuffer_ref.widenArray(buf, segIdx, + segIdx + len); + } + buf[segIdx++] = type; + len--; + // small arraycopy (2, 4 or 6) but with offset: + System.arraycopy(pts, off, buf, segIdx, len); + firstSegidx = segIdx + len; + } + @Override - public void lineTo(float x1, float y1) { - float dx = x1 - x0; - float dy = y1 - y0; + public void lineTo(final float x1, final float y1) { + final float dx = x1 - x0; + final float dy = y1 - y0; float len = dx*dx + dy*dy; if (len == 0.0f) { @@ -308,48 +322,61 @@ final float[] _curCurvepts = curCurvepts; final float[] _dash = dash; + final int _dashLen = this.dashLen; + + int _idx = idx; + boolean _dashOn = dashOn; + float _phase = phase; float leftInThisDashSegment; - float dashdx, dashdy, p; + float d, dashdx, dashdy, p; while (true) { - leftInThisDashSegment = _dash[idx] - phase; + d = _dash[_idx]; + leftInThisDashSegment = d - _phase; if (len <= leftInThisDashSegment) { _curCurvepts[0] = x1; _curCurvepts[1] = y1; - goTo(_curCurvepts, 0, 4); + + goTo(_curCurvepts, 0, 4, _dashOn); // Advance phase within current dash segment - phase += len; + _phase += len; + // TODO: compare float values using epsilon: if (len == leftInThisDashSegment) { - phase = 0.0f; - idx = (idx + 1) % dashLen; - dashOn = !dashOn; + _phase = 0.0f; + _idx = (_idx + 1) % _dashLen; + _dashOn = !_dashOn; } + + // Save local state: + idx = _idx; + dashOn = _dashOn; + phase = _phase; return; } - dashdx = _dash[idx] * cx; - dashdy = _dash[idx] * cy; + dashdx = d * cx; + dashdy = d * cy; - if (phase == 0.0f) { + if (_phase == 0.0f) { _curCurvepts[0] = x0 + dashdx; _curCurvepts[1] = y0 + dashdy; } else { - p = leftInThisDashSegment / _dash[idx]; + p = leftInThisDashSegment / d; _curCurvepts[0] = x0 + p * dashdx; _curCurvepts[1] = y0 + p * dashdy; } - goTo(_curCurvepts, 0, 4); + goTo(_curCurvepts, 0, 4, _dashOn); len -= leftInThisDashSegment; // Advance to next dash segment - idx = (idx + 1) % dashLen; - dashOn = !dashOn; - phase = 0.0f; + _idx = (_idx + 1) % _dashLen; + _dashOn = !_dashOn; + _phase = 0.0f; } } @@ -362,39 +389,55 @@ if (pointCurve(curCurvepts, type)) { return; } - li.initializeIterationOnCurve(curCurvepts, type); + final LengthIterator _li = li; + final float[] _curCurvepts = curCurvepts; + final float[] _dash = dash; + final int _dashLen = this.dashLen; + + _li.initializeIterationOnCurve(_curCurvepts, type); + + int _idx = idx; + boolean _dashOn = dashOn; + float _phase = phase; // initially the current curve is at curCurvepts[0...type] int curCurveoff = 0; float lastSplitT = 0.0f; float t; - float leftInThisDashSegment = dash[idx] - phase; + float leftInThisDashSegment = _dash[_idx] - _phase; - while ((t = li.next(leftInThisDashSegment)) < 1.0f) { + while ((t = _li.next(leftInThisDashSegment)) < 1.0f) { if (t != 0.0f) { Helpers.subdivideAt((t - lastSplitT) / (1.0f - lastSplitT), - curCurvepts, curCurveoff, - curCurvepts, 0, - curCurvepts, type, type); + _curCurvepts, curCurveoff, + _curCurvepts, 0, + _curCurvepts, type, type); lastSplitT = t; - goTo(curCurvepts, 2, type); + goTo(_curCurvepts, 2, type, _dashOn); curCurveoff = type; } // Advance to next dash segment - idx = (idx + 1) % dashLen; - dashOn = !dashOn; - phase = 0.0f; - leftInThisDashSegment = dash[idx]; - } - goTo(curCurvepts, curCurveoff+2, type); - phase += li.lastSegLen(); - if (phase >= dash[idx]) { - phase = 0.0f; - idx = (idx + 1) % dashLen; - dashOn = !dashOn; - } + _idx = (_idx + 1) % _dashLen; + _dashOn = !_dashOn; + _phase = 0.0f; + leftInThisDashSegment = _dash[_idx]; + } + + goTo(_curCurvepts, curCurveoff + 2, type, _dashOn); + + _phase += _li.lastSegLen(); + if (_phase >= _dash[_idx]) { + _phase = 0.0f; + _idx = (_idx + 1) % _dashLen; + _dashOn = !_dashOn; + } + // Save local state: + idx = _idx; + dashOn = _dashOn; + phase = _phase; + // reset LengthIterator: - li.reset(); + _li.reset(); } private static boolean pointCurve(float[] curve, int type) { @@ -420,7 +463,7 @@ // tree; however, the trees we are interested in have the property that // every non leaf node has exactly 2 children static final class LengthIterator { - private enum Side {LEFT, RIGHT}; + private enum Side {LEFT, RIGHT} // Holds the curves at various levels of the recursion. The root // (i.e. the original curve) is at recCurveStack[0] (but then it // gets subdivided, the left half is put at 1, so most of the time @@ -670,11 +713,12 @@ // this is a bit of a hack. It returns -1 if we're not on a leaf, and // the length of the leaf if we are on a leaf. private float onLeaf() { - float[] curve = recCurveStack[recLevel]; + final float[] curve = recCurveStack[recLevel]; + final int _curveType = curveType; float polyLen = 0.0f; float x0 = curve[0], y0 = curve[1]; - for (int i = 2; i < curveType; i += 2) { + for (int i = 2; i < _curveType; i += 2) { final float x1 = curve[i], y1 = curve[i+1]; final float len = Helpers.linelen(x0, y0, x1, y1); polyLen += len; @@ -684,8 +728,8 @@ } final float lineLen = Helpers.linelen(curve[0], curve[1], - curve[curveType-2], - curve[curveType-1]); + curve[_curveType-2], + curve[_curveType-1]); if ((polyLen - lineLen) < ERR || recLevel == REC_LIMIT) { return (polyLen + lineLen) / 2.0f; } @@ -694,9 +738,9 @@ } @Override - public void curveTo(float x1, float y1, - float x2, float y2, - float x3, float y3) + public void curveTo(final float x1, final float y1, + final float x2, final float y2, + final float x3, final float y3) { final float[] _curCurvepts = curCurvepts; _curCurvepts[0] = x0; _curCurvepts[1] = y0; @@ -707,7 +751,9 @@ } @Override - public void quadTo(float x1, float y1, float x2, float y2) { + public void quadTo(final float x1, final float y1, + final float x2, final float y2) + { final float[] _curCurvepts = curCurvepts; _curCurvepts[0] = x0; _curCurvepts[1] = y0; _curCurvepts[2] = x1; _curCurvepts[3] = y1; @@ -718,7 +764,7 @@ @Override public void closePath() { lineTo(sx, sy); - if (firstSegidx > 0) { + if (firstSegidx != 0) { if (!dashOn || needsMoveTo) { out.moveTo(sx, sy); } @@ -729,7 +775,7 @@ @Override public void pathDone() { - if (firstSegidx > 0) { + if (firstSegidx != 0) { out.moveTo(sx, sy); emitFirstSegments(); }