Allow selecting unit (px/mm) in Canvas::Stroke.

By directly specifying the desired end result to the renderer, we
can avoid regeneration of geometry.
This commit is contained in:
EvilSpirit 2016-06-30 21:54:35 +06:00 committed by whitequark
parent a5c7fc6ad9
commit 9f97e9aad4
7 changed files with 77 additions and 13 deletions

View File

@ -79,11 +79,9 @@ void Constraint::DoLabel(Canvas *canvas, Canvas::hStroke hcs,
}
void Constraint::DoProjectedPoint(Canvas *canvas, Canvas::hStroke hcs, Vector *r) {
const Camera &camera = canvas->GetCamera();
Canvas::Stroke strokeStippled = *canvas->strokes.FindById(hcs);
strokeStippled.stipplePattern = StipplePattern::SHORT_DASH;
strokeStippled.stippleScale = 4.0 / camera.scale;
strokeStippled.stippleScale = 4.0;
Canvas::hStroke hcsStippled = canvas->GetStroke(strokeStippled);
Vector p = r->ProjectInto(workplane);
@ -542,7 +540,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
case Type::PROJ_PT_DISTANCE: {
Canvas::Stroke strokeStippled = stroke;
strokeStippled.stipplePattern = StipplePattern::SHORT_DASH;
strokeStippled.stippleScale = 4.0 / camera.scale;
strokeStippled.stippleScale = 4.0;
Canvas::hStroke hcsStippled = canvas->GetStroke(strokeStippled);
Vector ap = SK.GetEntity(ptA)->PointGetNum(),

View File

@ -499,6 +499,7 @@ void Entity::Draw(DrawAs how, Canvas *canvas) {
pointStroke.zIndex = IsPoint() ? zIndex + 1 : 0;
pointStroke.color = stroke.color;
pointStroke.width = 7.0;
pointStroke.unit = Canvas::Unit::PX;
Canvas::hStroke hcsPoint = canvas->GetStroke(pointStroke);
switch(type) {
@ -627,7 +628,7 @@ void Entity::Draw(DrawAs how, Canvas *canvas) {
Canvas::Stroke strokeBorder = stroke;
strokeBorder.zIndex -= 3;
strokeBorder.stipplePattern = StipplePattern::SHORT_DASH;
strokeBorder.stippleScale = 8.0 / camera.scale;
strokeBorder.stippleScale = 8.0;
Canvas::hStroke hcsBorder = canvas->GetStroke(strokeBorder);
double textHeight = Style::TextHeight(hs) / camera.scale;

View File

@ -137,6 +137,50 @@ bool Canvas::Stroke::Equals(const Stroke &other) const {
stippleScale == other.stippleScale);
}
double Canvas::Stroke::WidthMm(const Camera &camera) const {
switch(unit) {
case Canvas::Unit::MM:
return width;
case Canvas::Unit::PX:
return width / camera.scale;
default:
ssassert(false, "Unexpected unit");
}
}
double Canvas::Stroke::WidthPx(const Camera &camera) const {
switch(unit) {
case Canvas::Unit::MM:
return width * camera.scale;
case Canvas::Unit::PX:
return width;
default:
ssassert(false, "Unexpected unit");
}
}
double Canvas::Stroke::StippleScaleMm(const Camera &camera) const {
switch(unit) {
case Canvas::Unit::MM:
return stippleScale;
case Canvas::Unit::PX:
return stippleScale / camera.scale;
default:
ssassert(false, "Unexpected unit");
}
}
double Canvas::Stroke::StippleScalePx(const Camera &camera) const {
switch(unit) {
case Canvas::Unit::MM:
return stippleScale * camera.scale;
case Canvas::Unit::PX:
return stippleScale;
default:
ssassert(false, "Unexpected unit");
}
}
bool Canvas::Fill::Equals(const Fill &other) const {
return (layer == other.layer &&
zIndex == other.zIndex &&

View File

@ -87,6 +87,12 @@ public:
CONTOUR_ONLY // Contour outlines only
};
// Stroke widths, etc, can be scale-invariant (in pixels) or scale-dependent (in millimeters).
enum class Unit {
MM,
PX
};
class Stroke {
public:
hStroke h;
@ -95,11 +101,17 @@ public:
int zIndex;
RgbaColor color;
double width;
Unit unit;
StipplePattern stipplePattern;
double stippleScale;
void Clear() { *this = {}; }
bool Equals(const Stroke &other) const;
double WidthMm(const Camera &camera) const;
double WidthPx(const Camera &camera) const;
double StippleScaleMm(const Camera &camera) const;
double StippleScalePx(const Camera &camera) const;
};
enum class FillPattern {

View File

@ -43,8 +43,9 @@ void CairoRenderer::SelectStroke(hStroke hcs) {
RgbaColor color = stroke->color;
std::vector<double> dashes =
StipplePatternDashes(stroke->stipplePattern, stroke->stippleScale * camera.scale);
cairo_set_line_width(context, stroke->width);
StipplePatternDashes(stroke->stipplePattern,
stroke->StippleScalePx(camera));
cairo_set_line_width(context, stroke->WidthPx(camera));
cairo_set_dash(context, dashes.data(), dashes.size(), 0);
cairo_set_source_rgba(context, color.redF(), color.greenF(), color.blueF(),
color.alphaF());

View File

@ -191,7 +191,7 @@ Canvas::Stroke *OpenGl1Renderer::SelectStroke(hStroke hcs) {
UnSelectPrimitive();
ssglColorRGBA(stroke->color);
ssglDepthRange(stroke->layer, stroke->zIndex);
ssglLineWidth(stroke->width);
ssglLineWidth(stroke->WidthPx(camera));
// Fat lines and points are quads affected by glPolygonStipple, so make sure
// they are displayed correctly.
ssglFillPattern(FillPattern::SOLID);
@ -329,12 +329,12 @@ void OpenGl1Renderer::DoLine(const Vector &a, const Vector &b, hStroke hcs) {
if(a.Equals(b)) return;
Stroke *stroke = SelectStroke(hcs);
if(stroke->width <= 3.0) {
if(stroke->WidthPx(camera) <= 3.0) {
SelectPrimitive(GL_LINES);
ssglVertex3v(a);
ssglVertex3v(b);
} else {
DoFatLine(a, b, stroke->width / camera.scale);
DoFatLine(a, b, stroke->WidthPx(camera) / camera.scale);
}
}
@ -376,7 +376,7 @@ void OpenGl1Renderer::DoStippledLine(const Vector &a, const Vector &b, hStroke h
const char *si = patternSeq;
double end = len;
double ss = stroke->stippleScale / 2.0;
double ss = stroke->StippleScaleMm(camera) / 2.0;
do {
double start = end;
switch(*si) {
@ -400,7 +400,7 @@ void OpenGl1Renderer::DoStippledLine(const Vector &a, const Vector &b, hStroke h
case '.':
end = max(end - 0.5 * ss, 0.0);
if(end == 0.0) break;
DoPoint(a.Plus(dir.ScaledBy(end)), stroke->width);
DoPoint(a.Plus(dir.ScaledBy(end)), stroke->WidthPx(camera));
end = max(end - 0.5 * ss, 0.0);
break;

View File

@ -291,6 +291,14 @@ Canvas::Stroke Style::Stroke(hStyle hs) {
stroke.stipplePattern = style->stippleType;
stroke.stippleScale = Style::StippleScaleMm(hs);
stroke.width = Style::Width(hs.v);
switch(style->widthAs) {
case Style::UnitsAs::PIXELS:
stroke.unit = Canvas::Unit::PX;
break;
case Style::UnitsAs::MM:
stroke.unit = Canvas::Unit::MM;
break;
}
return stroke;
}