You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
4.0 KiB
180 lines
4.0 KiB
#include "StrokeView.h" |
|
#include "DocumentView.h" |
|
|
|
#include "model/eraser/EraseableStroke.h" |
|
#include "model/Stroke.h" |
|
#include "util/LoopUtil.h" |
|
|
|
StrokeView::StrokeView(cairo_t* cr, Stroke* s, int startPoint, double scaleFactor, bool noAlpha) |
|
: cr(cr), |
|
s(s), |
|
startPoint(startPoint), |
|
scaleFactor(scaleFactor), |
|
noAlpha(noAlpha) |
|
{ |
|
} |
|
|
|
StrokeView::~StrokeView() |
|
{ |
|
} |
|
|
|
void StrokeView::drawFillStroke() |
|
{ |
|
for_first_then_each( |
|
s->getPointVector(), |
|
[this](auto const& first) { cairo_move_to(this->cr, first.x, first.y); }, |
|
[this](auto const& other) { cairo_line_to(this->cr, other.x, other.y); }); |
|
|
|
cairo_fill(cr); |
|
} |
|
|
|
void StrokeView::applyDashed(double offset) |
|
{ |
|
const double* dashes = nullptr; |
|
int dashCount = 0; |
|
if (s->getLineStyle().getDashes(dashes, dashCount)) |
|
{ |
|
cairo_set_dash(cr, dashes, dashCount, offset); |
|
} |
|
else |
|
{ |
|
// Disable dash |
|
cairo_set_dash(cr, nullptr, 0, 0); |
|
} |
|
} |
|
|
|
void StrokeView::drawEraseableStroke(cairo_t* cr, Stroke* s) |
|
{ |
|
EraseableStroke* e = s->getEraseable(); |
|
e->draw(cr); |
|
} |
|
|
|
/** |
|
* Change cairo source, used to draw hilighter transparent, |
|
* but only if not currently drawing and so on (yes, complicated) |
|
*/ |
|
void StrokeView::changeCairoSource(bool markAudioStroke) |
|
{ |
|
/////////////////////////////////////////////////////// |
|
// Fill stroke |
|
/////////////////////////////////////////////////////// |
|
if (s->getFill() != -1 && s->getToolType() != STROKE_TOOL_HIGHLIGHTER) |
|
{ |
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
|
|
|
// Set the color and transparency |
|
DocumentView::applyColor(cr, s, s->getFill()); |
|
|
|
drawFillStroke(); |
|
} |
|
|
|
|
|
if (s->getToolType() == STROKE_TOOL_HIGHLIGHTER || |
|
(s->getAudioFilename().length() == 0 && markAudioStroke)) |
|
{ |
|
if (s->getToolType() == STROKE_TOOL_HIGHLIGHTER) { |
|
cairo_set_operator(cr, CAIRO_OPERATOR_MULTIPLY); |
|
} |
|
else { |
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
|
} |
|
|
|
// Set the color |
|
DocumentView::applyColor(cr, s, 120); |
|
} |
|
else |
|
{ |
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
|
// Set the color |
|
DocumentView::applyColor(cr, s); |
|
} |
|
} |
|
|
|
/** |
|
* No pressure sensitivity, one line is drawn |
|
*/ |
|
void StrokeView::drawNoPressure() |
|
{ |
|
int count = 1; |
|
double width = s->getWidth(); |
|
|
|
bool group = false; |
|
if (s->getFill() != -1 && s->getToolType() == STROKE_TOOL_HIGHLIGHTER) |
|
{ |
|
cairo_push_group(cr); |
|
// Do not apply the alpha here, else the border and the fill |
|
// are visible instead of one homogeneous area |
|
DocumentView::applyColor(cr, s, 255); |
|
drawFillStroke(); |
|
group = true; |
|
} |
|
|
|
// Set width |
|
cairo_set_line_width(cr, width * scaleFactor); |
|
applyDashed(0); |
|
|
|
for_first_then_each( |
|
s->getPointVector(), |
|
[this](auto const& first) { cairo_move_to(cr, first.x, first.y); }, |
|
[this](auto const& other) { cairo_line_to(cr, other.x, other.y); }); |
|
cairo_stroke(cr); |
|
|
|
if (group) |
|
{ |
|
cairo_pop_group_to_source(cr); |
|
|
|
if (noAlpha) |
|
{ |
|
// Currently drawing -> transparent applied on blitting |
|
cairo_paint(cr); |
|
} |
|
else |
|
{ |
|
cairo_paint_with_alpha(cr, s->getFill() / 255.0); |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Draw a stroke with pressure, for this multiple |
|
* lines with different widths needs to be drawn |
|
*/ |
|
void StrokeView::drawWithPressure() |
|
{ |
|
double dashOffset = 0; |
|
|
|
for (auto p1i = begin(s->getPointVector()), p2i = std::next(p1i), endi = end(s->getPointVector()); |
|
p1i != endi && p2i != endi; ++p1i, ++p2i) |
|
{ |
|
auto width = p1i->z != Point::NO_PRESSURE ? p1i->z : s->getWidth(); |
|
cairo_set_line_width(cr, width * scaleFactor); |
|
applyDashed(dashOffset); |
|
cairo_move_to(cr, p1i->x, p1i->y); |
|
cairo_line_to(cr, p2i->x, p2i->y); |
|
cairo_stroke(cr); |
|
dashOffset += p1i->lineLengthTo(*p2i); |
|
} |
|
} |
|
|
|
void StrokeView::paint(bool dontRenderEditingStroke) |
|
{ |
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); |
|
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); |
|
|
|
// don't render eraseable for previews |
|
if (s->getEraseable() && !dontRenderEditingStroke) |
|
{ |
|
drawEraseableStroke(cr, s); |
|
return; |
|
} |
|
|
|
// No pressure sensitivity, easy draw a line... |
|
if (!s->hasPressure() || s->getToolType() == STROKE_TOOL_HIGHLIGHTER) |
|
{ |
|
drawNoPressure(); |
|
} |
|
else |
|
{ |
|
drawWithPressure(); |
|
} |
|
}
|
|
|