/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.gef.draw2d.graphics; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.PathData; import org.xmind.gef.draw2d.geometry.PrecisionPoint; import org.xmind.gef.draw2d.geometry.PrecisionRectangle; public class Path extends org.eclipse.swt.graphics.Path { /** * @param device */ public Path(Device device) { super(device); } public Path(Device device, PathData data) { super(device, data); } /** * @see org.eclipse.swt.graphics.Path#moveTo(float, float) */ public void moveTo(PrecisionPoint p) { super.moveTo((float) p.x, (float) p.y); } public void moveTo(Point p) { super.moveTo(p.x, p.y); } /** * @see org.eclipse.swt.graphics.Path#lineTo(float, float) */ public void lineTo(PrecisionPoint p) { super.lineTo((float) p.x, (float) p.y); } public void lineTo(Point p) { super.lineTo(p.x, p.y); } /** * @see org.eclipse.swt.graphics.Path#cubicTo(float, float, float, float, * float, float) */ public void cubicTo(PrecisionPoint control1, PrecisionPoint control2, PrecisionPoint dest) { super.cubicTo((float) control1.x, (float) control1.y, (float) control2.x, (float) control2.y, (float) dest.x, (float) dest.y); } public void cubicTo(Point control1, Point control2, Point dest) { super.cubicTo(control1.x, control1.y, control2.x, control2.y, dest.x, dest.y); } /** * @see org.eclipse.swt.graphics.Path#quadTo(float, float, float, float) */ public void quadTo(PrecisionPoint control, PrecisionPoint dest) { super.quadTo((float) control.x, (float) control.y, (float) dest.x, (float) dest.y); } public void quadTo(Point control, Point dest) { super.quadTo(control.x, control.y, dest.x, dest.y); } public void addArc(PrecisionRectangle bounds, float startAngle, float arcAngle) { super.addArc((float) bounds.x, (float) bounds.y, (float) bounds.width, (float) bounds.height, startAngle, arcAngle); } public void addArc(Rectangle bounds, float startAngle, float arcAngle) { super.addArc(bounds.x, bounds.y, bounds.width, bounds.height, startAngle, arcAngle); } public void addRectangle(PrecisionRectangle bounds) { super.addRectangle((float) bounds.x, (float) bounds.y, (float) bounds.width, (float) bounds.height); } public void addRectangle(Rectangle bounds) { super.addRectangle(bounds.x, bounds.y, bounds.width, bounds.height); } public void addRoundedRectangle(Rectangle bounds, float corner) { addRoundedRectangle(bounds.x, bounds.y, bounds.width, bounds.height, corner); } public void addRoundedRectangleByRatio(Rectangle bounds, float cornerRatio) { addRoundedRectangle(bounds.x, bounds.y, bounds.width, bounds.height, Math.min(bounds.width, bounds.height) * cornerRatio); } public void addRoundedRectangle(PrecisionRectangle bounds, float corner) { addRoundedRectangle((float) bounds.x, (float) bounds.y, (float) bounds.width, (float) bounds.height, corner); } private static final float CORNER_CONTROL_RATIO = 0.447715f; public void addRoundedRectangle(float x, float y, float width, float height, float corner) { float r = x + width; float b = y + height; float x0 = x + width / 2; float y0 = y + height / 2; float x1 = Math.min(x + corner, x0); moveTo(x1, y); float y1 = Math.min(y + corner, y0); float cx1 = x + (x1 - x) * CORNER_CONTROL_RATIO; float cy1 = y + (y1 - y) * CORNER_CONTROL_RATIO; cubicTo(cx1, y, x, cy1, x, y1); float y2 = Math.max(b - corner, y0); lineTo(x, y2); float cy2 = b - (b - y2) * CORNER_CONTROL_RATIO; cubicTo(x, cy2, cx1, b, x1, b); float x2 = Math.max(r - corner, x0); lineTo(x2, b); float cx2 = r - (r - x2) * CORNER_CONTROL_RATIO; cubicTo(cx2, b, r, cy2, r, y2); lineTo(r, y1); cubicTo(r, cy1, cx2, y, x2, y); // float y1 = Math.min(y + corner, y0); // moveTo(x, y1); // float x1 = Math.min(x + corner, x0); // float cx1 = x + (x1 - x) * CORNER_CONTROL_RATIO; // float cy1 = y + (y1 - y) * CORNER_CONTROL_RATIO; // cubicTo(x, cy1, cx1, y, x1, y); // // float x2 = Math.max(r - corner, x0); // lineTo(x2, y); // // float cx2 = r - (r - x2) * CORNER_CONTROL_RATIO; // cubicTo(cx2, y, r, cy1, r, y1); // // float y2 = Math.max(b - corner, y0); // lineTo(r, y2); // // float cy2 = b - (b - y2) * CORNER_CONTROL_RATIO; // cubicTo(r, cy2, cx2, b, x2, b); // // lineTo(x1, b); // // cubicTo(cx1, b, x, cy2, x, y2); close(); } public void addRoundedPolygon(float corner, PrecisionPoint... points) { if (points == null || points.length < 3) return; float[] locs = new float[points.length * 2]; for (int i = 0; i < points.length; i++) { PrecisionPoint p = points[i]; locs[i * 2] = (float) p.x; locs[i * 2 + 1] = (float) p.y; } addRoundedPolygon(corner, locs); } public void addRoundedPolygon(float corner, float... locs) { if (locs == null || locs.length < 6) return; float qc = corner / 4; int len = locs.length; float[] last = null; for (int i = 0; i < len - 1; i += 2) { float x1 = locs[i]; float y1 = locs[i + 1]; float x2 = i < len - 2 ? locs[i + 2] : locs[i - len + 2]; float y2 = i < len - 2 ? locs[i + 3] : locs[i - len + 3]; float x3 = i < len - 4 ? locs[i + 4] : locs[i - len + 4]; float y3 = i < len - 4 ? locs[i + 5] : locs[i - len + 5]; if (last == null) { last = calcPoint(x1, y1, x2, y2, corner); moveTo(last[0], last[1]); } float[] p1 = calcPoint(x2, y2, x1, y1, corner); lineTo(p1[0], p1[1]); float[] c1 = calcPoint(x2, y2, x1, y1, qc); float[] c2 = calcPoint(x2, y2, x3, y3, qc); float[] p2 = calcPoint(x2, y2, x3, y3, corner); cubicTo(c1[0], c1[1], c2[0], c2[1], p2[0], p2[1]); last = p2; } close(); } private float[] calcPoint(float x1, float y1, float x2, float y2, float dist) { float x; float y; if (x1 == x2) { x = x1; if (y1 == y2) { y = y1; } else { y = y1 + dist; } } else { if (y1 == y2) { y = y1; x = x1 + dist; } else { float d = (x2 - x1) / (y2 - y1); float r = (float) (dist / Math.sqrt(d * d + 1)); if (y2 < y1) r = -r; y = r + y1; x = (y - y1) * d + x1; } } return new float[] { x, y }; } public void addString(String text, PrecisionPoint loc, Font font) { super.addString(text, (float) loc.x, (float) loc.y, font); } public void addString(String text, Point loc, Font font) { super.addString(text, loc.x, loc.y, font); } public PrecisionPoint getCurrentPoint() { float[] current = new float[2]; getCurrentPoint(current); return new PrecisionPoint(current[0], current[1]); } }