void Context::appendPath( const cinder::Path2d &path ) { size_t point = 0; if( path.empty() ) return; moveTo( path.getPoint( point++ ) ); for( size_t seg = 0; seg < path.getNumSegments(); ++seg ) { switch( path.getSegmentType( seg ) ) { case Path2d::LINETO: lineTo( path.getPoint( point++ ) ); break; case Path2d::QUADTO: { const Vec2f &spl0( path.getPoint( point - 1 ) ); const Vec2f &spl1( path.getPoint( point + 0 ) ); const Vec2f &spl2( path.getPoint( point + 1 ) ); curveTo( spl0 + (spl1 - spl0) / 3.0f * 2.0f, spl1 + (spl2 - spl1) / 3.0f, spl2 ); point += 2; } break; case Path2d::CUBICTO: curveTo( path.getPoint( point ), path.getPoint( point + 1 ), path.getPoint( point + 2 ) ); point += 3; break; case Path2d::CLOSE: closePath(); break; } } }
void ShapeMaker::cubicTo (const Bezier &cubic) { const double sqrt3 = 1.7320508075688772935274463415059; const double precision = 600 * 18 / (60 * factorx * sqrt3); // distance between control points of quadratic approximations of either end double D01 = (cubic.p1 - (cubic.c1 - cubic.c0) * 3 - cubic.p0).magnitude () / 2; double tMax3 = precision / D01; if (tMax3 >= 1) { curveTo (cubic.quadraticCtrl(), cubic.p1); return; } Bezier end(cubic); if (tMax3 >= 0.5 * 0.5 * 0.5) { Bezier start (end.split (0.5)); curveTo (start.quadraticCtrl (), start.p1); } else { double tMax = pow (tMax3, 1.0/3.0); Bezier start (end.split (tMax)); Bezier middle (end.split (1 - tMax / (1 - tMax))); curveTo (start.quadraticCtrl (), start.p1); cubicTo (middle); } curveTo (end.quadraticCtrl (), end.p1); }
void QgsDxfPaintEngine::drawPath( const QPainterPath& path ) { int pathLength = path.elementCount(); for ( int i = 0; i < pathLength; ++i ) { const QPainterPath::Element& pathElem = path.elementAt( i ); if ( pathElem.type == QPainterPath::MoveToElement ) { moveTo( pathElem.x, pathElem.y ); } else if ( pathElem.type == QPainterPath::LineToElement ) { lineTo( pathElem.x, pathElem.y ); } else if ( pathElem.type == QPainterPath::CurveToElement ) { curveTo( pathElem.x, pathElem.y ); } else if ( pathElem.type == QPainterPath::CurveToDataElement ) { mCurrentCurve.append( QPointF( pathElem.x, pathElem.y ) ); } } endCurve(); endPolygon(); }
void ShapeMaker::cubicToRec( const Point& a, const Point& b, const Point& c, const Point& d, double k, int iteration ) { Point s = intersectLines( a, b, c, d ); double dx = (a.x+d.x+s.x*4-(b.x+c.x)*3)*.125; double dy = (a.y+d.y+s.y*4-(b.y+c.y)*3)*.125; Bezier bz( a, b, c, d ); Bezier b0, b1; if( dx*dx + dy*dy > k && iteration<10 ) { // fprintf(stderr,"[%03i] split: %f\n", iteration, dx*dx + dy*dy); bezierSplit( bz, &b0, &b1 ); // recurse iteration++; cubicToRec( a, b0.p1, b0.p2, b0.p3, k, iteration ); //lineTo( b0.p3.x, b0.p3.y ); cubicToRec( b1.p0, b1.p1, b1.p2, d, k, iteration ); //lineTo( b1.p1.x, b1.p1.y ); //lineTo( b1.p2.x, b1.p2.y ); //lineTo( d.x, d.y ); } else { // fprintf(stderr,"#### %i %i %i %i\n", (int)s.x, (int)s.y, (int)d.x, (int)d.y ); //lineTo( (int)s.x, (int)s.y ); //lineTo( (int)d.x, (int)d.y ); curveTo( s.x, s.y, d.x, d.y ); } }
void PathParser::line_to(const Edge& curve) { if (curve.straight()) { lineTo(curve.ap); } else { curveTo(curve); } }
void ShapeMaker::ellipseSegment( double cx, double cy, double rx, double ry, double phi, double theta, double dTheta) { double a1 = theta + dTheta / 2; double a2 = theta + dTheta; double f = cos(dTheta / 2); Point p1(cos(a1) * rx / f, sin(a1) * ry / f); Point p2(cos(a2) * rx, sin(a2) * ry); p1.rotate(phi); p2.rotate(phi); curveTo(cx + p1.x, cy + p1.y, cx + p2.x, cy + p2.y); }
QT_FT_Outline *QOutlineMapper::convertPath(const QVectorPath &path) { int count = path.elementCount(); #ifdef QT_DEBUG_CONVERT printf("QOutlineMapper::convertPath(VP), size=%d\n", count); #endif beginOutline(path.hasWindingFill() ? Qt::WindingFill : Qt::OddEvenFill); if (path.elements()) { // TODO: if we do closing of subpaths in convertElements instead we // could avoid this loop const QPainterPath::ElementType *elements = path.elements(); const QPointF *points = reinterpret_cast<const QPointF *>(path.points()); for (int index = 0; index < count; ++index) { switch (elements[index]) { case QPainterPath::MoveToElement: if (index == count - 1) continue; moveTo(points[index]); break; case QPainterPath::LineToElement: lineTo(points[index]); break; case QPainterPath::CurveToElement: curveTo(points[index], points[index+1], points[index+2]); index += 2; break; default: break; // This will never hit.. } } } else { // ### We can kill this copying and just use the buffer straight... m_elements.resize(count); if (count) memcpy(m_elements.data(), path.points(), count* sizeof(QPointF)); m_element_types.resize(0); } endOutline(); return outline(); }
void KoConnectionShape::updatePath(const QSizeF &size) { Q_UNUSED(size); Q_D(KoConnectionShape); const qreal MinimumEscapeLength = (qreal)20.; clear(); switch (d->connectionType) { case Standard: { d->normalPath(MinimumEscapeLength); if (d->path.count() != 0){ moveTo(d->path[0]); for (int index = 1; index < d->path.count(); ++index) lineTo(d->path[index]); } break; } case Lines: { QPointF direction1 = d->escapeDirection(0); QPointF direction2 = d->escapeDirection(d->handles.count() - 1); moveTo(d->handles[StartHandle]); if (! direction1.isNull()) lineTo(d->handles[StartHandle] + MinimumEscapeLength * direction1); if (! direction2.isNull()) lineTo(d->handles[EndHandle] + MinimumEscapeLength * direction2); lineTo(d->handles[EndHandle]); break; } case Straight: moveTo(d->handles[StartHandle]); lineTo(d->handles[EndHandle]); break; case Curve: // TODO QPointF direction1 = d->escapeDirection(0); QPointF direction2 = d->escapeDirection(d->handles.count() - 1); moveTo(d->handles[StartHandle]); if (! direction1.isNull() && ! direction2.isNull()) { QPointF curvePoint1 = d->handles[StartHandle] + 5.0 * MinimumEscapeLength * direction1; QPointF curvePoint2 = d->handles[EndHandle] + 5.0 * MinimumEscapeLength * direction2; curveTo(curvePoint1, curvePoint2, d->handles[EndHandle]); } else { lineTo(d->handles[EndHandle]); } break; } normalize(); }
void Knob::initPath() { double data[DATA_LEN][DATA_LEN]; for (int i=0;i<DATA_LEN;i++) { for (int j=0;j<DATA_LEN;j++) { data[i][j] = ctl[i][j]; } } jitter (data, XVARY, YVARY, XDBVARY, XDFVARY); cPath.setFillRule(Qt::WindingFill); cPathReverse.setFillRule(Qt::WindingFill); cPath.moveTo(data[0][X],data[0][Y]); cPathReverse.moveTo(data[DATA_LEN-1][X],data[DATA_LEN-1][Y]); for (int i = 0; i < (DATA_LEN-1); i++) { curveTo (cPath, data, i, true); curveTo (cPathReverse, data, DATA_LEN-1-i, false); } // Transform to coincide with line segment (x1,y1)-(x2,y2) QMatrix affine(x2-x1, y2-y1, y1-y2, x2-x1, x1, y1); cPath=affine.map(cPath); cPathReverse=affine.map(cPathReverse); }
QT_FT_Outline *QOutlineMapper::convertPath(const QPainterPath &path) { Q_ASSERT(!path.isEmpty()); int elmCount = path.elementCount(); #ifdef QT_DEBUG_CONVERT printf("QOutlineMapper::convertPath(), size=%d\n", elmCount); #endif beginOutline(path.fillRule()); for (int index=0; index<elmCount; ++index) { const QPainterPath::Element &elm = path.elementAt(index); switch (elm.type) { case QPainterPath::MoveToElement: if (index == elmCount - 1) continue; moveTo(elm); break; case QPainterPath::LineToElement: lineTo(elm); break; case QPainterPath::CurveToElement: curveTo(elm, path.elementAt(index + 1), path.elementAt(index + 2)); index += 2; break; default: break; // This will never hit.. } } endOutline(); return outline(); }
//---------------------------------------------------------- void ofPath::curveTo(float x, float y, float z){ curveTo(ofPoint(x,y,z)); }
//---------------------------------------------------------- void ofPath::curveTo(float x, float y){ curveTo(glm::vec3(x,y,0)); }
void cff_parseOutline(uint8_t *data, uint32_t len, cff_Index gsubr, cff_Index lsubr, cff_Stack *stack, void *outline, cff_IOutlineBuilder methods, const otfcc_Options *options) { uint16_t gsubr_bias = compute_subr_bias(gsubr.count); uint16_t lsubr_bias = compute_subr_bias(lsubr.count); uint8_t *start = data; uint32_t advance, i, cnt_bezier; cff_Value val; void (*setWidth)(void *context, double width) = methods.setWidth; void (*newContour)(void *context) = methods.newContour; void (*lineTo)(void *context, double x1, double y1) = methods.lineTo; void (*curveTo)(void *context, double x1, double y1, double x2, double y2, double x3, double y3) = methods.curveTo; void (*setHint)(void *context, bool isVertical, double position, double width) = methods.setHint; void (*setMask)(void *context, bool isContourMask, bool *mask) = methods.setMask; double (*getrand)(void *context) = methods.getrand; if (!setWidth) setWidth = callback_nopSetWidth; if (!newContour) newContour = callback_nopNewContour; if (!lineTo) lineTo = callback_nopLineTo; if (!curveTo) curveTo = callback_nopCurveTo; if (!setHint) setHint = callback_nopsetHint; if (!setMask) setMask = callback_nopsetMask; if (!getrand) getrand = callback_nopgetrand; while (start < data + len) { advance = cff_decodeCS2Token(start, &val); switch (val.t) { case CS2_OPERATOR: switch (val.i) { case op_hstem: case op_vstem: case op_hstemhm: case op_vstemhm: if (stack->index % 2) setWidth(outline, stack->stack[0].d); stack->stem += stack->index >> 1; double hintBase = 0; for (uint16_t j = stack->index % 2; j < stack->index; j += 2) { double pos = stack->stack[j].d; double width = stack->stack[j + 1].d; setHint(outline, (val.i == op_vstem || val.i == op_vstemhm), pos + hintBase, width); hintBase += pos + width; } stack->index = 0; break; case op_hintmask: case op_cntrmask: { if (stack->index % 2) setWidth(outline, stack->stack[0].d); bool isVertical = stack->stem > 0; stack->stem += stack->index >> 1; double hintBase = 0; for (uint16_t j = stack->index % 2; j < stack->index; j += 2) { double pos = stack->stack[j].d; double width = stack->stack[j + 1].d; setHint(outline, isVertical, pos + hintBase, width); hintBase += pos + width; } uint32_t maskLength = (stack->stem + 7) >> 3; bool *mask; NEW(mask, stack->stem + 7); for (uint32_t byte = 0; byte < maskLength; byte++) { uint8_t maskByte = start[advance + byte]; mask[(byte << 3) + 0] = maskByte >> 7 & 1; mask[(byte << 3) + 1] = maskByte >> 6 & 1; mask[(byte << 3) + 2] = maskByte >> 5 & 1; mask[(byte << 3) + 3] = maskByte >> 4 & 1; mask[(byte << 3) + 4] = maskByte >> 3 & 1; mask[(byte << 3) + 5] = maskByte >> 2 & 1; mask[(byte << 3) + 6] = maskByte >> 1 & 1; mask[(byte << 3) + 7] = maskByte >> 0 & 1; } setMask(outline, (val.i == op_cntrmask), mask); advance += maskLength; stack->index = 0; break; } case op_vmoveto: { CHECK_STACK_TOP(op_vmoveto, 1); if (stack->index > 1) setWidth(outline, stack->stack[stack->index - 2].d); newContour(outline); lineTo(outline, 0.0, stack->stack[stack->index - 1].d); stack->index = 0; break; } case op_rmoveto: { CHECK_STACK_TOP(op_rmoveto, 2); if (stack->index > 2) setWidth(outline, stack->stack[stack->index - 3].d); newContour(outline); lineTo(outline, stack->stack[stack->index - 2].d, stack->stack[stack->index - 1].d); stack->index = 0; break; } case op_hmoveto: { CHECK_STACK_TOP(op_hmoveto, 1); if (stack->index > 1) setWidth(outline, stack->stack[stack->index - 2].d); newContour(outline); lineTo(outline, stack->stack[stack->index - 1].d, 0.0); stack->index = 0; break; } case op_endchar: { if (stack->index > 0) setWidth(outline, stack->stack[stack->index - 1].d); break; } case op_rlineto: { for (i = 0; i < stack->index; i += 2) lineTo(outline, stack->stack[i].d, stack->stack[i + 1].d); stack->index = 0; break; } case op_vlineto: { if (stack->index % 2 == 1) { lineTo(outline, 0.0, stack->stack[0].d); for (i = 1; i < stack->index; i += 2) { lineTo(outline, stack->stack[i].d, 0.0); lineTo(outline, 0.0, stack->stack[i + 1].d); } } else { for (i = 0; i < stack->index; i += 2) { lineTo(outline, 0.0, stack->stack[i].d); lineTo(outline, stack->stack[i + 1].d, 0.0); } } stack->index = 0; break; } case op_hlineto: { if (stack->index % 2 == 1) { lineTo(outline, stack->stack[0].d, 0.0); for (i = 1; i < stack->index; i += 2) { lineTo(outline, 0.0, stack->stack[i].d); lineTo(outline, stack->stack[i + 1].d, 0.0); } } else { for (i = 0; i < stack->index; i += 2) { lineTo(outline, stack->stack[i].d, 0.0); lineTo(outline, 0.0, stack->stack[i + 1].d); } } stack->index = 0; break; } case op_rrcurveto: { for (i = 0; i < stack->index; i += 6) curveTo(outline, stack->stack[i].d, stack->stack[i + 1].d, stack->stack[i + 2].d, stack->stack[i + 3].d, stack->stack[i + 4].d, stack->stack[i + 5].d); stack->index = 0; break; } case op_rcurveline: { for (i = 0; i < stack->index - 2; i += 6) curveTo(outline, stack->stack[i].d, stack->stack[i + 1].d, stack->stack[i + 2].d, stack->stack[i + 3].d, stack->stack[i + 4].d, stack->stack[i + 5].d); lineTo(outline, stack->stack[stack->index - 2].d, stack->stack[stack->index - 1].d); stack->index = 0; break; } case op_rlinecurve: { for (i = 0; i < stack->index - 6; i += 2) lineTo(outline, stack->stack[i].d, stack->stack[i + 1].d); curveTo(outline, stack->stack[stack->index - 6].d, stack->stack[stack->index - 5].d, stack->stack[stack->index - 4].d, stack->stack[stack->index - 3].d, stack->stack[stack->index - 2].d, stack->stack[stack->index - 1].d); stack->index = 0; break; } case op_vvcurveto: { if (stack->index % 4 == 1) { curveTo(outline, stack->stack[0].d, stack->stack[1].d, stack->stack[2].d, stack->stack[3].d, 0.0, stack->stack[4].d); for (i = 5; i < stack->index; i += 4) curveTo(outline, 0.0, stack->stack[i].d, stack->stack[i + 1].d, stack->stack[i + 2].d, 0.0, stack->stack[i + 3].d); } else { for (i = 0; i < stack->index; i += 4) curveTo(outline, 0.0, stack->stack[i].d, stack->stack[i + 1].d, stack->stack[i + 2].d, 0.0, stack->stack[i + 3].d); } stack->index = 0; break; } case op_hhcurveto: { if (stack->index % 4 == 1) { curveTo(outline, stack->stack[1].d, stack->stack[0].d, stack->stack[2].d, stack->stack[3].d, stack->stack[4].d, 0.0); for (i = 5; i < stack->index; i += 4) curveTo(outline, stack->stack[i].d, 0.0, stack->stack[i + 1].d, stack->stack[i + 2].d, stack->stack[i + 3].d, 0.0); } else { for (i = 0; i < stack->index; i += 4) curveTo(outline, stack->stack[i].d, 0.0, stack->stack[i + 1].d, stack->stack[i + 2].d, stack->stack[i + 3].d, 0.0); } stack->index = 0; break; } case op_vhcurveto: { if (stack->index % 4 == 1) cnt_bezier = (stack->index - 5) / 4; else cnt_bezier = (stack->index / 4); for (i = 0; i < 4 * cnt_bezier; i += 4) { if ((i / 4) % 2 == 0) curveTo(outline, 0.0, stack->stack[i].d, stack->stack[i + 1].d, stack->stack[i + 2].d, stack->stack[i + 3].d, 0.0); else curveTo(outline, stack->stack[i].d, 0.0, stack->stack[i + 1].d, stack->stack[i + 2].d, 0.0, stack->stack[i + 3].d); } if (stack->index % 8 == 5) { curveTo(outline, 0.0, stack->stack[stack->index - 5].d, stack->stack[stack->index - 4].d, stack->stack[stack->index - 3].d, stack->stack[stack->index - 2].d, stack->stack[stack->index - 1].d); } if (stack->index % 8 == 1) { curveTo(outline, stack->stack[stack->index - 5].d, 0.0, stack->stack[stack->index - 4].d, stack->stack[stack->index - 3].d, stack->stack[stack->index - 1].d, stack->stack[stack->index - 2].d); } stack->index = 0; break; } case op_hvcurveto: { if (stack->index % 4 == 1) cnt_bezier = (stack->index - 5) / 4; else cnt_bezier = (stack->index / 4); for (i = 0; i < 4 * cnt_bezier; i += 4) { if ((i / 4) % 2 == 0) curveTo(outline, stack->stack[i].d, 0.0, stack->stack[i + 1].d, stack->stack[i + 2].d, 0.0, stack->stack[i + 3].d); else curveTo(outline, 0.0, stack->stack[i].d, stack->stack[i + 1].d, stack->stack[i + 2].d, stack->stack[i + 3].d, 0.0); } if (stack->index % 8 == 5) { curveTo(outline, stack->stack[stack->index - 5].d, 0.0, stack->stack[stack->index - 4].d, stack->stack[stack->index - 3].d, stack->stack[stack->index - 1].d, stack->stack[stack->index - 2].d); } if (stack->index % 8 == 1) { curveTo(outline, 0.0, stack->stack[stack->index - 5].d, stack->stack[stack->index - 4].d, stack->stack[stack->index - 3].d, stack->stack[stack->index - 2].d, stack->stack[stack->index - 1].d); } stack->index = 0; break; } case op_hflex: { CHECK_STACK_TOP(op_hflex, 7); curveTo(outline, stack->stack[0].d, 0.0, stack->stack[1].d, stack->stack[2].d, stack->stack[3].d, 0.0); curveTo(outline, stack->stack[4].d, 0.0, stack->stack[5].d, -stack->stack[2].d, stack->stack[6].d, 0.0); stack->index = 0; break; } case op_flex: { CHECK_STACK_TOP(op_flex, 12); curveTo(outline, stack->stack[0].d, stack->stack[1].d, stack->stack[2].d, stack->stack[3].d, stack->stack[4].d, stack->stack[5].d); curveTo(outline, stack->stack[6].d, stack->stack[7].d, stack->stack[8].d, stack->stack[9].d, stack->stack[10].d, stack->stack[11].d); stack->index = 0; break; } case op_hflex1: { CHECK_STACK_TOP(op_hflex1, 9); curveTo(outline, stack->stack[0].d, stack->stack[1].d, stack->stack[2].d, stack->stack[3].d, stack->stack[4].d, 0.0); curveTo(outline, stack->stack[5].d, 0.0, stack->stack[6].d, stack->stack[7].d, stack->stack[8].d, -(stack->stack[1].d + stack->stack[3].d + stack->stack[7].d)); stack->index = 0; break; } case op_flex1: { CHECK_STACK_TOP(op_flex1, 11); double dx = stack->stack[0].d + stack->stack[2].d + stack->stack[4].d + stack->stack[6].d + stack->stack[8].d; double dy = stack->stack[1].d + stack->stack[3].d + stack->stack[5].d + stack->stack[7].d + stack->stack[9].d; if (fabs(dx) > fabs(dy)) { dx = stack->stack[10].d; dy = -dy; } else { dx = -dx; dy = stack->stack[10].d; } curveTo(outline, stack->stack[0].d, stack->stack[1].d, stack->stack[2].d, stack->stack[3].d, stack->stack[4].d, stack->stack[5].d); curveTo(outline, stack->stack[6].d, stack->stack[7].d, stack->stack[8].d, stack->stack[9].d, dx, dy); stack->index = 0; break; } case op_and: { CHECK_STACK_TOP(op_and, 2); double num1 = stack->stack[stack->index - 1].d; double num2 = stack->stack[stack->index - 2].d; stack->stack[stack->index - 2].d = (num1 && num2) ? 1.0 : 0.0; stack->index -= 1; break; } case op_or: { CHECK_STACK_TOP(op_or, 2); double num1 = stack->stack[stack->index - 1].d; double num2 = stack->stack[stack->index - 2].d; stack->stack[stack->index - 2].d = (num1 || num2) ? 1.0 : 0.0; stack->index -= 1; break; } case op_not: { CHECK_STACK_TOP(op_not, 1); double num = stack->stack[stack->index - 1].d; stack->stack[stack->index - 1].d = num ? 0.0 : 1.0; break; } case op_abs: { CHECK_STACK_TOP(op_abs, 1); double num = stack->stack[stack->index - 1].d; stack->stack[stack->index - 1].d = (num < 0.0) ? -num : num; break; } case op_add: { CHECK_STACK_TOP(op_add, 2); double num1 = stack->stack[stack->index - 1].d; double num2 = stack->stack[stack->index - 2].d; stack->stack[stack->index - 2].d = num1 + num2; stack->index -= 1; break; } case op_sub: { CHECK_STACK_TOP(op_sub, 2); double num1 = stack->stack[stack->index - 2].d; double num2 = stack->stack[stack->index - 1].d; stack->stack[stack->index - 2].d = num1 - num2; stack->index -= 1; break; } case op_div: { CHECK_STACK_TOP(op_div, 2); double num1 = stack->stack[stack->index - 2].d; double num2 = stack->stack[stack->index - 1].d; stack->stack[stack->index - 2].d = num1 / num2; stack->index -= 1; break; } case op_neg: { CHECK_STACK_TOP(op_neg, 1); double num = stack->stack[stack->index - 1].d; stack->stack[stack->index - 1].d = -num; break; } case op_eq: { CHECK_STACK_TOP(op_eq, 2); double num1 = stack->stack[stack->index - 1].d; double num2 = stack->stack[stack->index - 2].d; stack->stack[stack->index - 2].d = (num1 == num2) ? 1.0 : 0.0; stack->index -= 1; break; } case op_drop: { CHECK_STACK_TOP(op_drop, 1); stack->index -= 1; break; } case op_put: { CHECK_STACK_TOP(op_put, 2); double val = stack->stack[stack->index - 2].d; int32_t i = (int32_t)stack->stack[stack->index - 1].d; stack->transient[i % type2_transient_array].d = val; stack->index -= 2; break; } case op_get: { CHECK_STACK_TOP(op_get, 1); int32_t i = (int32_t)stack->stack[stack->index - 1].d; stack->stack[stack->index - 1].d = stack->transient[i % type2_transient_array].d; break; } case op_ifelse: { CHECK_STACK_TOP(op_ifelse, 4); double v2 = stack->stack[stack->index - 1].d; double v1 = stack->stack[stack->index - 2].d; double s2 = stack->stack[stack->index - 3].d; double s1 = stack->stack[stack->index - 4].d; stack->stack[stack->index - 4].d = (v1 <= v2) ? s1 : s2; stack->index -= 3; break; } case op_random: { // Chosen from a fair dice // TODO: use a real randomizer stack->stack[stack->index].t = cff_DOUBLE; stack->stack[stack->index].d = getrand(outline); stack->index += 1; break; } case op_mul: { CHECK_STACK_TOP(op_mul, 2); double num1 = stack->stack[stack->index - 1].d; double num2 = stack->stack[stack->index - 2].d; stack->stack[stack->index - 2].d = num1 * num2; stack->index -= 1; break; } case op_sqrt: { CHECK_STACK_TOP(op_sqrt, 1); double num = stack->stack[stack->index - 1].d; stack->stack[stack->index - 1].d = sqrt(num); break; } case op_dup: { CHECK_STACK_TOP(op_dup, 1); stack->stack[stack->index] = stack->stack[stack->index - 1]; stack->index += 1; break; } case op_exch: { CHECK_STACK_TOP(op_exch, 2); double num1 = stack->stack[stack->index - 1].d; double num2 = stack->stack[stack->index - 2].d; stack->stack[stack->index - 1].d = num2; stack->stack[stack->index - 2].d = num1; break; } case op_index: { CHECK_STACK_TOP(op_index, 2); uint8_t n = stack->index - 1; uint8_t j = n - 1 - (uint8_t)(stack->stack[n].d) % n; stack->stack[n] = stack->stack[j]; break; } case op_roll: { CHECK_STACK_TOP(op_roll, 2); int32_t j = stack->stack[stack->index - 1].d; uint32_t n = stack->stack[stack->index - 2].d; CHECK_STACK_TOP(op_roll, 2 + n); j = -j % n; if (j < 0) j += n; if (!j) break; uint8_t last = stack->index - 3; uint8_t first = stack->index - 2 - n; reverseStack(stack, first, last); reverseStack(stack, last - j + 1, last); reverseStack(stack, first, last - j); stack->index -= 2; break; } case op_return: return; case op_callsubr: { CHECK_STACK_TOP(op_callsubr, 1); uint32_t subr = (uint32_t)stack->stack[--(stack->index)].d; cff_parseOutline(lsubr.data + lsubr.offset[lsubr_bias + subr] - 1, lsubr.offset[lsubr_bias + subr + 1] - lsubr.offset[lsubr_bias + subr], gsubr, lsubr, stack, outline, methods, options); break; } case op_callgsubr: { CHECK_STACK_TOP(op_callgsubr, 1); uint32_t subr = (uint32_t)stack->stack[--(stack->index)].d; cff_parseOutline(gsubr.data + gsubr.offset[gsubr_bias + subr] - 1, gsubr.offset[gsubr_bias + subr + 1] - gsubr.offset[gsubr_bias + subr], gsubr, lsubr, stack, outline, methods, options); break; } } break; case CS2_OPERAND: case CS2_FRACTION: stack->stack[(stack->index)++] = val; break; } start += advance; } }
static void lineTo(Ppolyline_t * path, double x, double y) { pointf curp = path->ps[path->pn - 1]; curveTo(path, curp.x, curp.y, x, y, x, y); }
/* genEllipticPath: * Approximate an elliptical arc via Beziers of given degree * threshold indicates quality of approximation * if isSlice is true, the path begins and ends with line segments * to the center of the ellipse. * Returned path must be freed by the caller. */ static Ppolyline_t *genEllipticPath(ellipse_t * ep, int degree, double threshold, boolean isSlice) { double dEta; double etaB; double cosEtaB; double sinEtaB; double aCosEtaB; double bSinEtaB; double aSinEtaB; double bCosEtaB; double xB; double yB; double xBDot; double yBDot; double t; double alpha; Ppolyline_t *path = NEW(Ppolyline_t); // find the number of Bezier curves needed boolean found = FALSE; int i, n = 1; while ((!found) && (n < 1024)) { double dEta = (ep->eta2 - ep->eta1) / n; if (dEta <= 0.5 * M_PI) { double etaB = ep->eta1; found = TRUE; for (i = 0; found && (i < n); ++i) { double etaA = etaB; etaB += dEta; found = (estimateError(ep, degree, etaA, etaB) <= threshold); } } n = n << 1; } dEta = (ep->eta2 - ep->eta1) / n; etaB = ep->eta1; cosEtaB = cos(etaB); sinEtaB = sin(etaB); aCosEtaB = ep->a * cosEtaB; bSinEtaB = ep->b * sinEtaB; aSinEtaB = ep->a * sinEtaB; bCosEtaB = ep->b * cosEtaB; xB = ep->cx + aCosEtaB * ep->cosTheta - bSinEtaB * ep->sinTheta; yB = ep->cy + aCosEtaB * ep->sinTheta + bSinEtaB * ep->cosTheta; xBDot = -aSinEtaB * ep->cosTheta - bCosEtaB * ep->sinTheta; yBDot = -aSinEtaB * ep->sinTheta + bCosEtaB * ep->cosTheta; if (isSlice) { moveTo(path, ep->cx, ep->cy); lineTo(path, xB, yB); } else { moveTo(path, xB, yB); } t = tan(0.5 * dEta); alpha = sin(dEta) * (sqrt(4 + 3 * t * t) - 1) / 3; for (i = 0; i < n; ++i) { double xA = xB; double yA = yB; double xADot = xBDot; double yADot = yBDot; etaB += dEta; cosEtaB = cos(etaB); sinEtaB = sin(etaB); aCosEtaB = ep->a * cosEtaB; bSinEtaB = ep->b * sinEtaB; aSinEtaB = ep->a * sinEtaB; bCosEtaB = ep->b * cosEtaB; xB = ep->cx + aCosEtaB * ep->cosTheta - bSinEtaB * ep->sinTheta; yB = ep->cy + aCosEtaB * ep->sinTheta + bSinEtaB * ep->cosTheta; xBDot = -aSinEtaB * ep->cosTheta - bCosEtaB * ep->sinTheta; yBDot = -aSinEtaB * ep->sinTheta + bCosEtaB * ep->cosTheta; if (degree == 1) { lineTo(path, xB, yB); #if DO_QUAD } else if (degree == 2) { double k = (yBDot * (xB - xA) - xBDot * (yB - yA)) / (xADot * yBDot - yADot * xBDot); quadTo(path, (xA + k * xADot), (yA + k * yADot), xB, yB); #endif } else { curveTo(path, (xA + alpha * xADot), (yA + alpha * yADot), (xB - alpha * xBDot), (yB - alpha * yBDot), xB, yB); } } endPath(path, isSlice); return path; }
//---------------------------------------------------------- void ofPath::curveTo(float x, float y){ curveTo(ofPoint(x,y,0)); }
//---------------------------------------------------------- void ofPath::curveTo(float x, float y, float z){ curveTo(glm::vec3(x,y,z)); }
void ShapeMaker::smoothCurveTo( double ax, double ay ) { curveTo( lastx + smoothx, lasty + smoothy, ax, ay ); }
//---------------------------------------------------------- void ofPath::curveTo(const glm::vec2 & p){ curveTo(glm::vec3(p, 0.0)); }