void PdfFileWriter::StartPath(RgbColor strokeRgb, double lineWidth, bool filled, RgbColor fillRgb) { fprintf(f, "1 J 1 j " // round endcaps and joins "%.3f w " "%.3f %.3f %.3f RG\r\n", MmToPts(lineWidth), strokeRgb.redF(), strokeRgb.greenF(), strokeRgb.blueF()); if(filled) { fprintf(f, "%.3f %.3f %.3f rg\r\n", fillRgb.redF(), fillRgb.greenF(), fillRgb.blueF()); } prevPt = Vector::From(VERY_POSITIVE, VERY_POSITIVE, VERY_POSITIVE); }
void GraphicsWindow::Selection::Draw(void) { Vector refp = Vector::From(0, 0, 0); if(entity.v) { Entity *e = SK.GetEntity(entity); e->Draw(); if(emphasized) refp = e->GetReferencePos(); } if(constraint.v) { Constraint *c = SK.GetConstraint(constraint); c->Draw(); if(emphasized) refp = c->GetReferencePos(); } if(emphasized && (constraint.v || entity.v)) { // We want to emphasize this constraint or entity, by drawing a thick // line from the top left corner of the screen to the reference point // of that entity or constraint. double s = 0.501/SS.GW.scale; Vector topLeft = SS.GW.projRight.ScaledBy(-SS.GW.width*s); topLeft = topLeft.Plus(SS.GW.projUp.ScaledBy(SS.GW.height*s)); topLeft = topLeft.Minus(SS.GW.offset); glLineWidth(40); RgbColor rgb = Style::Color(Style::HOVERED); glColor4d(rgb.redF(), rgb.greenF(), rgb.blueF(), 0.2); glBegin(GL_LINES); ssglVertex3v(topLeft); ssglVertex3v(refp); glEnd(); glLineWidth(1); } }
void EpsFileWriter::FinishPath(RgbColor strokeRgb, double lineWidth, bool filled, RgbColor fillRgb) { fprintf(f, " %.3f setlinewidth\r\n" " %.3f %.3f %.3f setrgbcolor\r\n" " 1 setlinejoin\r\n" // rounded " 1 setlinecap\r\n" // rounded " gsave stroke grestore\r\n", MmToPts(lineWidth), strokeRgb.redF(), strokeRgb.greenF(), strokeRgb.blueF()); if(filled) { fprintf(f, " %.3f %.3f %.3f setrgbcolor\r\n" " gsave fill grestore\r\n", fillRgb.redF(), fillRgb.greenF(), fillRgb.blueF()); } }
//----------------------------------------------------------------------------- // If a color is almost white, then we can rewrite it to black, just so that // it won't disappear on file formats with a light background. //----------------------------------------------------------------------------- RgbColor Style::RewriteColor(RgbColor rgbin) { Vector rgb = Vector::From(rgbin.redF(), rgbin.greenF(), rgbin.blueF()); rgb = rgb.Minus(Vector::From(1, 1, 1)); if(rgb.Magnitude() < 0.4 && SS.fixExportColors) { // This is an almost-white color in a default style, which is // good for the default on-screen view (black bg) but probably // not desired in the exported files, which typically are shown // against white backgrounds. return RGBi(0, 0, 0); } else { return rgbin; } }
void TextWindow::ShowListOfStyles(void) { Printf(true, "%Ft color style-name"); bool darkbg = false; Style *s; for(s = SK.style.First(); s; s = SK.style.NextAfter(s)) { Printf(false, "%Bp %Bz %Bp %Fl%Ll%f%D%s%E", darkbg ? 'd' : 'a', &s->color, darkbg ? 'd' : 'a', ScreenShowStyleInfo, s->h.v, s->DescriptionString()); darkbg = !darkbg; } Printf(true, " %Fl%Ll%fcreate a new custom style%E", &ScreenCreateCustomStyle); Printf(false, ""); RgbColor rgb = SS.backgroundColor; Printf(false, "%Ft background color (r, g, b)%E"); Printf(false, "%Ba %@, %@, %@ %Fl%D%f%Ll[change]%E", rgb.redF(), rgb.greenF(), rgb.blueF(), top[rows-1] + 2, &ScreenChangeBackgroundColor); Printf(false, ""); Printf(false, "%Ft background bitmap image%E"); if(SS.bgImage.fromFile) { Printf(false, "%Ba %Ftwidth:%E %dpx %Ftheight:%E %dpx", SS.bgImage.w, SS.bgImage.h); Printf(false, " %Ftscale:%E %# px/%s %Fl%Ll%f%D[change]%E", SS.bgImage.scale*SS.MmPerUnit(), SS.UnitName(), &ScreenChangeBackgroundImageScale, top[rows-1] + 2); Printf(false, "%Ba %Fl%Lc%fclear background image%E", &ScreenBackgroundImage); } else { Printf(false, "%Ba none - %Fl%Ll%fload background image%E", &ScreenBackgroundImage); Printf(false, " (bottom left will be center of view)"); } Printf(false, ""); Printf(false, " %Fl%Ll%fload factory defaults%E", &ScreenLoadFactoryDefaultStyles); }
void GraphicsWindow::Paint(void) { int i; havePainted = true; int w, h; GetGraphicsWindowSize(&w, &h); width = w; height = h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glScaled(scale*2.0/w, scale*2.0/h, scale*1.0/30000); double mat[16]; // Last thing before display is to apply the perspective double clp = SS.CameraTangent()*scale; MakeMatrix(mat, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, clp, 1); glMultMatrixd(mat); // Before that, we apply the rotation Vector n = projUp.Cross(projRight); MakeMatrix(mat, projRight.x, projRight.y, projRight.z, 0, projUp.x, projUp.y, projUp.z, 0, n.x, n.y, n.z, 0, 0, 0, 0, 1); glMultMatrixd(mat); // And before that, the translation MakeMatrix(mat, 1, 0, 0, offset.x, 0, 1, 0, offset.y, 0, 0, 1, offset.z, 0, 0, 0, 1); glMultMatrixd(mat); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glShadeModel(GL_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); // don't enable GL_POLYGON_SMOOTH; that looks ugly on some graphics cards, // drawn with leaks in the mesh glEnable(GL_POLYGON_OFFSET_LINE); glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_DEPTH_TEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_NORMALIZE); // At the same depth, we want later lines drawn over earlier. glDepthFunc(GL_LEQUAL); if(SS.AllGroupsOkay()) { glClearColor(SS.backgroundColor.redF(), SS.backgroundColor.greenF(), SS.backgroundColor.blueF(), 1.0f); } else { // Draw a different background whenever we're having solve problems. RgbColor rgb = Style::Color(Style::DRAW_ERROR); glClearColor(0.4f*rgb.redF(), 0.4f*rgb.greenF(), 0.4f*rgb.blueF(), 1.0f); // And show the text window, which has info to debug it ForceTextWindowShown(); } glClear(GL_COLOR_BUFFER_BIT); glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); if(SS.bgImage.fromFile) { // If a background image is loaded, then we draw it now as a texture. // This handles the resizing for us nicely. glBindTexture(GL_TEXTURE_2D, TEXTURE_BACKGROUND_IMG); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SS.bgImage.rw, SS.bgImage.rh, 0, GL_RGB, GL_UNSIGNED_BYTE, SS.bgImage.fromFile); double tw = ((double)SS.bgImage.w) / SS.bgImage.rw, th = ((double)SS.bgImage.h) / SS.bgImage.rh; double mmw = SS.bgImage.w / SS.bgImage.scale, mmh = SS.bgImage.h / SS.bgImage.scale; Vector origin = SS.bgImage.origin; origin = origin.DotInToCsys(projRight, projUp, n); // Place the depth of our origin at the point that corresponds to // w = 1, so that it's unaffected by perspective. origin.z = (offset.ScaledBy(-1)).Dot(n); origin = origin.ScaleOutOfCsys(projRight, projUp, n); // Place the background at the very back of the Z order, though, by // mucking with the depth range. glDepthRange(1, 1); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2d(0, 0); ssglVertex3v(origin); glTexCoord2d(0, th); ssglVertex3v(origin.Plus(projUp.ScaledBy(mmh))); glTexCoord2d(tw, th); ssglVertex3v(origin.Plus(projRight.ScaledBy(mmw).Plus( projUp. ScaledBy(mmh)))); glTexCoord2d(tw, 0); ssglVertex3v(origin.Plus(projRight.ScaledBy(mmw))); glEnd(); glDisable(GL_TEXTURE_2D); } ssglDepthRangeOffset(0); // Nasty case when we're reloading the imported files; could be that // we get an error, so a dialog pops up, and a message loop starts, and // we have to get called to paint ourselves. If the sketch is screwed // up, then we could trigger an oops trying to draw. if(!SS.allConsistent) return; // Let's use two lights, at the user-specified locations GLfloat f; glEnable(GL_LIGHT0); f = (GLfloat)SS.lightIntensity[0]; GLfloat li0[] = { f, f, f, 1.0f }; glLightfv(GL_LIGHT0, GL_DIFFUSE, li0); glLightfv(GL_LIGHT0, GL_SPECULAR, li0); glEnable(GL_LIGHT1); f = (GLfloat)SS.lightIntensity[1]; GLfloat li1[] = { f, f, f, 1.0f }; glLightfv(GL_LIGHT1, GL_DIFFUSE, li1); glLightfv(GL_LIGHT1, GL_SPECULAR, li1); Vector ld; ld = VectorFromProjs(SS.lightDir[0]); GLfloat ld0[4] = { (GLfloat)ld.x, (GLfloat)ld.y, (GLfloat)ld.z, 0 }; glLightfv(GL_LIGHT0, GL_POSITION, ld0); ld = VectorFromProjs(SS.lightDir[1]); GLfloat ld1[4] = { (GLfloat)ld.x, (GLfloat)ld.y, (GLfloat)ld.z, 0 }; glLightfv(GL_LIGHT1, GL_POSITION, ld1); if(SS.drawBackFaces) { // For debugging, draw the backs of the triangles in red, so that we // notice when a shell is open glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1); } else { glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 0); } GLfloat ambient[4] = { (float)SS.ambientIntensity, (float)SS.ambientIntensity, (float)SS.ambientIntensity, 1 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); ssglUnlockColor(); if(showSnapGrid && LockedInWorkplane()) { hEntity he = ActiveWorkplane(); EntityBase *wrkpl = SK.GetEntity(he), *norm = wrkpl->Normal(); Vector wu, wv, wn, wp; wp = SK.GetEntity(wrkpl->point[0])->PointGetNum(); wu = norm->NormalU(); wv = norm->NormalV(); wn = norm->NormalN(); double g = SS.gridSpacing; double umin = VERY_POSITIVE, umax = VERY_NEGATIVE, vmin = VERY_POSITIVE, vmax = VERY_NEGATIVE; int a; for(a = 0; a < 4; a++) { // Ideally, we would just do +/- half the width and height; but // allow some extra slop for rounding. Vector horiz = projRight.ScaledBy((0.6*width)/scale + 2*g), vert = projUp. ScaledBy((0.6*height)/scale + 2*g); if(a == 2 || a == 3) horiz = horiz.ScaledBy(-1); if(a == 1 || a == 3) vert = vert. ScaledBy(-1); Vector tp = horiz.Plus(vert).Minus(offset); // Project the point into our grid plane, normal to the screen // (not to the grid plane). If the plane is on edge then this is // impossible so don't try to draw the grid. bool parallel; Vector tpp = Vector::AtIntersectionOfPlaneAndLine( wn, wn.Dot(wp), tp, tp.Plus(n), ¶llel); if(parallel) goto nogrid; tpp = tpp.Minus(wp); double uu = tpp.Dot(wu), vv = tpp.Dot(wv); umin = min(uu, umin); umax = max(uu, umax); vmin = min(vv, vmin); vmax = max(vv, vmax); } int i, j, i0, i1, j0, j1; i0 = (int)(umin / g); i1 = (int)(umax / g); j0 = (int)(vmin / g); j1 = (int)(vmax / g); if(i0 > i1 || i1 - i0 > 400) goto nogrid; if(j0 > j1 || j1 - j0 > 400) goto nogrid; glLineWidth(1); ssglColorRGBa(Style::Color(Style::DATUM), 0.3); glBegin(GL_LINES); for(i = i0 + 1; i < i1; i++) { ssglVertex3v(wp.Plus(wu.ScaledBy(i*g)).Plus(wv.ScaledBy(j0*g))); ssglVertex3v(wp.Plus(wu.ScaledBy(i*g)).Plus(wv.ScaledBy(j1*g))); } for(j = j0 + 1; j < j1; j++) { ssglVertex3v(wp.Plus(wu.ScaledBy(i0*g)).Plus(wv.ScaledBy(j*g))); ssglVertex3v(wp.Plus(wu.ScaledBy(i1*g)).Plus(wv.ScaledBy(j*g))); } glEnd(); // Clear the depth buffer, so that the grid is at the very back of // the Z order. glClear(GL_DEPTH_BUFFER_BIT); nogrid:; } // Draw the active group; this does stuff like the mesh and edges. (SK.GetGroup(activeGroup))->Draw(); // Now draw the entities if(showHdnLines) glDisable(GL_DEPTH_TEST); Entity::DrawAll(); // Draw filled paths in all groups, when those filled paths were requested // specially by assigning a style with a fill color, or when the filled // paths are just being filled by default. This should go last, to make // the transparency work. Group *g; for(g = SK.group.First(); g; g = SK.group.NextAfter(g)) { if(!(g->IsVisible())) continue; g->DrawFilledPaths(); } glDisable(GL_DEPTH_TEST); // Draw the constraints for(i = 0; i < SK.constraint.n; i++) { SK.constraint.elem[i].Draw(); } // Draw the traced path, if one exists glLineWidth(Style::Width(Style::ANALYZE)); ssglColorRGB(Style::Color(Style::ANALYZE)); SContour *sc = &(SS.traced.path); glBegin(GL_LINE_STRIP); for(i = 0; i < sc->l.n; i++) { ssglVertex3v(sc->l.elem[i].p); } glEnd(); // And the naked edges, if the user did Analyze -> Show Naked Edges. glLineWidth(Style::Width(Style::DRAW_ERROR)); ssglColorRGB(Style::Color(Style::DRAW_ERROR)); ssglDrawEdges(&(SS.nakedEdges), true); // Then redraw whatever the mouse is hovering over, highlighted. glDisable(GL_DEPTH_TEST); ssglLockColorTo(Style::Color(Style::HOVERED)); hover.Draw(); // And finally draw the selection, same mechanism. ssglLockColorTo(Style::Color(Style::SELECTED)); for(Selection *s = selection.First(); s; s = selection.NextAfter(s)) { s->Draw(); } ssglUnlockColor(); // If a marquee selection is in progress, then draw the selection // rectangle, as an outline and a transparent fill. if(pending.operation == DRAGGING_MARQUEE) { Point2d begin = ProjectPoint(orig.marqueePoint); double xmin = min(orig.mouse.x, begin.x), xmax = max(orig.mouse.x, begin.x), ymin = min(orig.mouse.y, begin.y), ymax = max(orig.mouse.y, begin.y); Vector tl = UnProjectPoint(Point2d::From(xmin, ymin)), tr = UnProjectPoint(Point2d::From(xmax, ymin)), br = UnProjectPoint(Point2d::From(xmax, ymax)), bl = UnProjectPoint(Point2d::From(xmin, ymax)); glLineWidth((GLfloat)1.3); ssglColorRGB(Style::Color(Style::HOVERED)); glBegin(GL_LINE_LOOP); ssglVertex3v(tl); ssglVertex3v(tr); ssglVertex3v(br); ssglVertex3v(bl); glEnd(); ssglColorRGBa(Style::Color(Style::HOVERED), 0.10); glBegin(GL_QUADS); ssglVertex3v(tl); ssglVertex3v(tr); ssglVertex3v(br); ssglVertex3v(bl); glEnd(); } // An extra line, used to indicate the origin when rotating within the // plane of the monitor. if(SS.extraLine.draw) { glLineWidth(1); ssglLockColorTo(Style::Color(Style::DATUM)); glBegin(GL_LINES); ssglVertex3v(SS.extraLine.ptA); ssglVertex3v(SS.extraLine.ptB); glEnd(); } // A note to indicate the origin in the just-exported file. if(SS.justExportedInfo.draw) { ssglColorRGB(Style::Color(Style::DATUM)); Vector p = SS.justExportedInfo.pt, u = SS.justExportedInfo.u, v = SS.justExportedInfo.v; glLineWidth(1.5); glBegin(GL_LINES); ssglVertex3v(p.Plus(u.WithMagnitude(-15/scale))); ssglVertex3v(p.Plus(u.WithMagnitude(30/scale))); ssglVertex3v(p.Plus(v.WithMagnitude(-15/scale))); ssglVertex3v(p.Plus(v.WithMagnitude(30/scale))); glEnd(); ssglWriteText("(x, y) = (0, 0) for file just exported", DEFAULT_TEXT_HEIGHT, p.Plus(u.ScaledBy(10/scale)).Plus(v.ScaledBy(10/scale)), u, v, NULL, NULL); ssglWriteText("press Esc to clear this message", DEFAULT_TEXT_HEIGHT, p.Plus(u.ScaledBy(40/scale)).Plus( v.ScaledBy(-(DEFAULT_TEXT_HEIGHT)/scale)), u, v, NULL, NULL); } // And finally the toolbar. if(SS.showToolbar) { ToolbarDraw(); } }
void ssglColorRGBa(RgbColor rgb, double a) { if(!ColorLocked) glColor4d(rgb.redF(), rgb.greenF(), rgb.blueF(), a); }
void ssglLockColorTo(RgbColor rgb) { ColorLocked = false; glColor3d(rgb.redF(), rgb.greenF(), rgb.blueF()); ColorLocked = true; }