From 9f97e9aad42b68b3a0a877baaef7e42ed858d99f Mon Sep 17 00:00:00 2001 From: EvilSpirit Date: Thu, 30 Jun 2016 21:54:35 +0600 Subject: [PATCH] Allow selecting unit (px/mm) in Canvas::Stroke. By directly specifying the desired end result to the renderer, we can avoid regeneration of geometry. --- src/drawconstraint.cpp | 6 ++---- src/drawentity.cpp | 5 +++-- src/render/render.cpp | 44 ++++++++++++++++++++++++++++++++++++++ src/render/render.h | 12 +++++++++++ src/render/rendercairo.cpp | 5 +++-- src/render/rendergl1.cpp | 10 ++++----- src/style.cpp | 8 +++++++ 7 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/drawconstraint.cpp b/src/drawconstraint.cpp index 8828802..4033306 100644 --- a/src/drawconstraint.cpp +++ b/src/drawconstraint.cpp @@ -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(), diff --git a/src/drawentity.cpp b/src/drawentity.cpp index f48682d..373f6bf 100644 --- a/src/drawentity.cpp +++ b/src/drawentity.cpp @@ -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) { @@ -555,7 +556,7 @@ void Entity::Draw(DrawAs how, Canvas *canvas) { if(!SK.GetGroup(group)->IsVisible() || !SS.GW.showNormals) continue; } - stroke.layer = (asReference) ? Canvas::Layer::FRONT : Canvas::Layer::NORMAL; + stroke.layer = (asReference) ? Canvas::Layer::FRONT : Canvas::Layer::NORMAL; if(how != DrawAs::HOVERED && how != DrawAs::SELECTED) { // Always draw the x, y, and z axes in red, green, and blue; // brighter for the ones at the bottom left of the screen, @@ -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; diff --git a/src/render/render.cpp b/src/render/render.cpp index e080e40..a819aad 100644 --- a/src/render/render.cpp +++ b/src/render/render.cpp @@ -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 && diff --git a/src/render/render.h b/src/render/render.h index 7709276..a0b042b 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -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 { diff --git a/src/render/rendercairo.cpp b/src/render/rendercairo.cpp index d5e7753..ed0accb 100644 --- a/src/render/rendercairo.cpp +++ b/src/render/rendercairo.cpp @@ -43,8 +43,9 @@ void CairoRenderer::SelectStroke(hStroke hcs) { RgbaColor color = stroke->color; std::vector 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()); diff --git a/src/render/rendergl1.cpp b/src/render/rendergl1.cpp index e467ea9..d1d8c8c 100644 --- a/src/render/rendergl1.cpp +++ b/src/render/rendergl1.cpp @@ -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; diff --git a/src/style.cpp b/src/style.cpp index c8fb33e..459d2f8 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -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; }