bool GiGraphics::drawRoundRect(const GiContext* ctx, const Box2d& rect, float rx, float ry, bool modelUnit) { if (m_impl->drawRefcnt == 0 || rect.isEmpty()) return false; GiLock lock (&m_impl->drawRefcnt); bool ret = false; if (ry < _MGZERO) ry = rx; if (!DRAW_RECT(m_impl, modelUnit).isIntersect(rect)) // 全部在显示区域外 return false; if (rx < _MGZERO) { Point2d points[4] = { rect.leftBottom(), rect.rightBottom(), rect.rightTop(), rect.leftTop() }; return drawPolygon(ctx, 4, points); } else { Point2d points[16]; mgRoundRectToBeziers(points, rect, rx, ry); S2D(xf(), modelUnit).TransformPoints(16, points); ret = rawBeginPath(); if (ret) { ret = rawMoveTo(points[0].x, points[0].y); ret = rawBezierTo(&points[1], 3); ret = rawLineTo(points[4].x, points[4].y); ret = rawBezierTo(&points[5], 3); ret = rawLineTo(points[8].x, points[8].y); ret = rawBezierTo(&points[9], 3); ret = rawLineTo(points[12].x, points[12].y); ret = rawBezierTo(&points[13], 3); ret = rawClosePath(); ret = rawEndPath(ctx, true); } } return ret; }
bool GiGraphics::drawRoundRect(const GiContext* ctx, const Box2d& rect, float rx, float ry, bool modelUnit) { if (rect.isEmpty() || isStopping()) return false; bool ret = false; if (ry < _MGZERO) ry = rx; if (!DRAW_RECT(m_impl, modelUnit).isIntersect(rect)) // 全部在显示区域外 return false; if (rx < _MGZERO) { Point2d points[4] = { rect.leftBottom(), rect.rightBottom(), rect.rightTop(), rect.leftTop() }; return drawPolygon(ctx, 4, points); } else { Point2d pxs[16]; mgcurv::roundRectToBeziers(pxs, rect, rx, ry); S2D(xf(), modelUnit).transformPoints(16, pxs); ret = rawBeginPath(); if (ret) { rawMoveTo(pxs[0].x, pxs[0].y); rawBezierTo(pxs[1].x, pxs[1].y, pxs[2].x, pxs[2].y, pxs[3].x, pxs[3].y); rawLineTo(pxs[4].x, pxs[4].y); rawBezierTo(pxs[5].x, pxs[5].y, pxs[6].x, pxs[6].y, pxs[7].x, pxs[7].y); rawLineTo(pxs[8].x, pxs[8].y); rawBezierTo(pxs[9].x, pxs[9].y, pxs[10].x, pxs[10].y, pxs[11].x, pxs[11].y); rawLineTo(pxs[12].x, pxs[12].y); rawBezierTo(pxs[13].x, pxs[13].y, pxs[14].x, pxs[14].y, pxs[15].x, pxs[15].y); rawClosePath(); ret = rawEndPath(ctx, true); } } return ret; }
bool GiGraphics::drawPath_(const GiContext* ctx, const MgPath& path, bool fill, const Matrix2d& matD) { int n = path.getCount(); if (n == 0 || isStopping()) return false; const Point2d* pts = path.getPoints(); const char* types = path.getTypes(); Point2d ends, cp1, cp2; bool matsame = matD.isIdentity(); rawBeginPath(); for (int i = 0; i < n; i++) { switch (types[i] & ~kMgCloseFigure) { case kMgMoveTo: ends = matsame ? pts[i] : (pts[i] * matD); rawMoveTo(ends.x, ends.y); break; case kMgLineTo: ends = matsame ? pts[i] : (pts[i] * matD); rawLineTo(ends.x, ends.y); break; case kMgBezierTo: if (i + 2 >= n) return false; cp1 = matsame ? pts[i] : (pts[i] * matD); cp2 = matsame ? pts[i+1] : (pts[i+1] * matD); ends = matsame ? pts[i+2] : (pts[i+2] * matD); rawBezierTo(cp1.x, cp1.y, cp2.x, cp2.y, ends.x, ends.y); i += 2; break; case kMgQuadTo: if (i + 1 >= n) return false; cp1 = matsame ? pts[i] : (pts[i] * matD); ends = matsame ? pts[i+1] : (pts[i+1] * matD); rawQuadTo(cp1.x, cp1.y, ends.x, ends.y); i++; break; default: return false; } if (types[i] & kMgCloseFigure) rawClosePath(); } return rawEndPath(ctx, fill); }
bool GiGraphics::drawQuadSplines(const GiContext* ctx, int count, const Point2d* ctlpts, bool modelUnit) { if (m_impl->drawRefcnt == 0 || count < 3 || ctlpts == NULL) return false; GiLock lock (&m_impl->drawRefcnt); const Box2d wndrect (DRAW_RECT(m_impl, modelUnit)); const Matrix2d matD(S2D(xf(), modelUnit)); Point2d mid1, mid2, pt, pt2; int n = 0; rawBeginPath(); for (int i = 0; i + 2 < count; i++) { if (Box2d(3, ctlpts + i).isIntersect(wndrect)) { pt2 = ctlpts[i+2]; mid1 = (ctlpts[i] + ctlpts[i+1]) / 2 * matD; mid2 = (ctlpts[i+1] + pt2) / 2 * matD; if (n++ == 0) { pt = ctlpts[i] * matD; rawMoveTo(pt.x, pt.y); rawLineTo(mid1.x, mid1.y); } pt = ctlpts[i+1] * matD; rawQuadTo(pt.x, pt.y, mid2.x, mid2.y); } else if (n > 0) { pt = pt2 * matD; rawLineTo(pt.x, pt.y); n = 0; } } if (n > 0) { pt = pt2 * matD; rawLineTo(pt.x, pt.y); } return rawEndPath(ctx, false); }
bool GiGraphics::drawPath(const GiContext* ctx, const GiPath& path, bool fill, bool modelUnit) { int n = path.getCount(); if (n == 0) return false; Matrix2d matD(S2D(xf(), modelUnit)); const Point2d* pts = path.getPoints(); const char* types = path.getTypes(); Point2d a, b, c; rawBeginPath(); for (int i = 0; i < n; i++) { switch (types[i] & ~kGiCloseFigure) { case kGiMoveTo: a = pts[i] * matD; rawMoveTo(a.x, a.y); break; case kGiLineTo: a = pts[i] * matD; rawLineTo(a.x, a.y); break; case kGiBeziersTo: if (i + 2 >= n) return false; a = pts[i] * matD; b = pts[i+1] * matD; c = pts[i+2] * matD; rawBezierTo(a.x, a.y, b.x, b.y, c.x, c.y); i += 2; break; default: return false; } if (types[i] & kGiCloseFigure) rawClosePath(); } return rawEndPath(ctx, fill); }
bool GiGraphics::drawPie(const GiContext* ctx, const Point2d& center, float rx, float ry, float startAngle, float sweepAngle, bool modelUnit) { if (m_impl->drawRefcnt == 0 || rx < _MGZERO || fabsf(sweepAngle) < 1e-5f) return false; GiLock lock (&m_impl->drawRefcnt); if (ry < _MGZERO) ry = rx; const Box2d extent (center, rx*2.f, ry*2.f); // 模型坐标范围 if (!DRAW_RECT(m_impl, modelUnit).isIntersect(extent)) // 全部在显示区域外 return false; Point2d pxs[16]; int count = mgcurv::arcToBezier(pxs, center, rx, ry, startAngle, sweepAngle); if (count < 4) return false; S2D(xf(), modelUnit).TransformPoints(count, pxs); Point2d cen(center * S2D(xf(), modelUnit)); bool ret = rawBeginPath(); if (ret) { rawMoveTo(cen.x, cen.y); rawLineTo(pxs[0].x, pxs[0].y); for (int i = 1; i + 2 < count; i += 3) { rawBezierTo(pxs[i].x, pxs[i].y, pxs[i+1].x, pxs[i+1].y, pxs[i+2].x, pxs[i+2].y); } rawClosePath(); ret = rawEndPath(ctx, true); } return ret; }