109 // logic we can estimate the length of the outline edges based on |
109 // logic we can estimate the length of the outline edges based on |
110 // the radius + a pen width and adjusting for scale factors |
110 // the radius + a pen width and adjusting for scale factors |
111 // depending on if the pen is cosmetic or not. |
111 // depending on if the pen is cosmetic or not. |
112 // |
112 // |
113 // The curvyness value of PI/14 was based on, |
113 // The curvyness value of PI/14 was based on, |
114 // arcLength=2*PI*r/4=PI/2 and splitting length into somewhere |
114 // arcLength = 2*PI*r/4 = PI*r/2 and splitting length into somewhere |
115 // between 3 and 8 where 5 seemed to be give pretty good results |
115 // between 3 and 8 where 5 seemed to be give pretty good results |
116 // hence: Q_PI/14. Lower divisors will give more detail at the |
116 // hence: Q_PI/14. Lower divisors will give more detail at the |
117 // direct cost of performance. |
117 // direct cost of performance. |
118 |
118 |
119 // simplfy pens that are thin in device size (2px wide or less) |
119 // simplfy pens that are thin in device size (2px wide or less) |
479 { |
479 { |
480 Q_ASSERT(0); // The dasher should not produce curves... |
480 Q_ASSERT(0); // The dasher should not produce curves... |
481 } |
481 } |
482 |
482 |
483 QDashedStrokeProcessor::QDashedStrokeProcessor() |
483 QDashedStrokeProcessor::QDashedStrokeProcessor() |
484 : m_dash_stroker(0), m_inv_scale(1) |
484 : m_points(0), m_types(0), |
|
485 m_dash_stroker(0), m_inv_scale(1) |
485 { |
486 { |
486 m_dash_stroker.setMoveToHook(qdashprocessor_moveTo); |
487 m_dash_stroker.setMoveToHook(qdashprocessor_moveTo); |
487 m_dash_stroker.setLineToHook(qdashprocessor_lineTo); |
488 m_dash_stroker.setLineToHook(qdashprocessor_lineTo); |
488 m_dash_stroker.setCubicToHook(qdashprocessor_cubicTo); |
489 m_dash_stroker.setCubicToHook(qdashprocessor_cubicTo); |
489 } |
490 } |
490 |
491 |
491 void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen) |
492 void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen, const QRectF &clip) |
492 { |
493 { |
493 |
494 |
494 const qreal *pts = path.points(); |
495 const qreal *pts = path.points(); |
495 const QPainterPath::ElementType *types = path.elements(); |
496 const QPainterPath::ElementType *types = path.elements(); |
496 int count = path.elementCount(); |
497 int count = path.elementCount(); |
497 |
498 |
|
499 bool cosmetic = pen.isCosmetic(); |
|
500 |
498 m_points.reset(); |
501 m_points.reset(); |
499 m_types.reset(); |
502 m_types.reset(); |
|
503 m_points.reserve(path.elementCount()); |
|
504 m_types.reserve(path.elementCount()); |
500 |
505 |
501 qreal width = qpen_widthf(pen); |
506 qreal width = qpen_widthf(pen); |
502 if (width == 0) |
507 if (width == 0) |
503 width = 1; |
508 width = 1; |
504 |
509 |
505 m_dash_stroker.setDashPattern(pen.dashPattern()); |
510 m_dash_stroker.setDashPattern(pen.dashPattern()); |
506 m_dash_stroker.setStrokeWidth(pen.isCosmetic() ? width * m_inv_scale : width); |
511 m_dash_stroker.setStrokeWidth(cosmetic ? width * m_inv_scale : width); |
507 m_dash_stroker.setMiterLimit(pen.miterLimit()); |
512 m_dash_stroker.setMiterLimit(pen.miterLimit()); |
508 qreal curvyness = sqrt(width) * m_inv_scale / 8; |
513 m_dash_stroker.setClipRect(clip); |
|
514 |
|
515 float curvynessAdd, curvynessMul, roundness = 0; |
|
516 |
|
517 // simplfy pens that are thin in device size (2px wide or less) |
|
518 if (width < 2.5 && (cosmetic || m_inv_scale == 1)) { |
|
519 curvynessAdd = 0.5; |
|
520 curvynessMul = CURVE_FLATNESS / m_inv_scale; |
|
521 roundness = 1; |
|
522 } else if (cosmetic) { |
|
523 curvynessAdd= width / 2; |
|
524 curvynessMul= CURVE_FLATNESS; |
|
525 roundness = qMax<int>(4, width * CURVE_FLATNESS); |
|
526 } else { |
|
527 curvynessAdd = width * m_inv_scale; |
|
528 curvynessMul = CURVE_FLATNESS / m_inv_scale; |
|
529 roundness = qMax<int>(4, width * curvynessMul); |
|
530 } |
509 |
531 |
510 if (count < 2) |
532 if (count < 2) |
511 return; |
533 return; |
512 |
534 |
513 const qreal *endPts = pts + (count<<1); |
535 const qreal *endPts = pts + (count<<1); |
538 QBezier b = QBezier::fromPoints(*(((const QPointF *) pts) - 1), |
560 QBezier b = QBezier::fromPoints(*(((const QPointF *) pts) - 1), |
539 *(((const QPointF *) pts)), |
561 *(((const QPointF *) pts)), |
540 *(((const QPointF *) pts) + 1), |
562 *(((const QPointF *) pts) + 1), |
541 *(((const QPointF *) pts) + 2)); |
563 *(((const QPointF *) pts) + 2)); |
542 QRectF bounds = b.bounds(); |
564 QRectF bounds = b.bounds(); |
543 int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * curvyness); |
565 float rad = qMax(bounds.width(), bounds.height()); |
|
566 int threshold = qMin<float>(64, (rad + curvynessAdd) * curvynessMul); |
544 if (threshold < 4) |
567 if (threshold < 4) |
545 threshold = 4; |
568 threshold = 4; |
|
569 |
546 qreal threshold_minus_1 = threshold - 1; |
570 qreal threshold_minus_1 = threshold - 1; |
547 for (int i=0; i<threshold; ++i) { |
571 for (int i=0; i<threshold; ++i) { |
548 QPointF pt = b.pointAt(i / threshold_minus_1); |
572 QPointF pt = b.pointAt(i / threshold_minus_1); |
549 m_dash_stroker.lineTo(pt.x(), pt.y()); |
573 m_dash_stroker.lineTo(pt.x(), pt.y()); |
550 } |
574 } |