public TextWidget(string text, double x = 0, double y = 0, double pointSize = 12, Justification justification = Justification.Left, RGBA_Bytes textColor = new RGBA_Bytes(), bool ellipsisIfClipped = true, bool underline = false, RGBA_Bytes backgroundColor = new RGBA_Bytes()) { pointSize *= GlobalPointSizeScaleRatio; Selectable = false; DoubleBuffer = DoubleBufferDefault; AutoExpandBoundsToText = false; EllipsisIfClipped = ellipsisIfClipped; OriginRelativeParent = new Vector2(x, y); this.textColor = textColor; if (this.textColor.Alpha0To255 == 0) { // we assume it is the default if alpha 0. Also there is no reason to make a text color of this as it will draw nothing. this.textColor = RGBA_Bytes.Black; } if (backgroundColor.Alpha0To255 != 0) { BackgroundColor = backgroundColor; } base.Text = text; StyledTypeFace typeFaceStyle = new StyledTypeFace(LiberationSansFont.Instance, pointSize, underline); printer = new TypeFacePrinter(text, typeFaceStyle, justification: justification); LocalBounds = printer.LocalBounds; MinimumSize = new Vector2(LocalBounds.Width, LocalBounds.Height); }
private void AddCharacterMeshes(string currentText, TypeFacePrinter printer) { int newIndex = asynchMeshGroups.Count; StyledTypeFace typeFace = printer.TypeFaceStyle; for (int i = 0; i < currentText.Length; i++) { string letter = currentText[i].ToString(); TypeFacePrinter letterPrinter = new TypeFacePrinter(letter, typeFace); if (CharacterHasMesh(letterPrinter, letter)) { Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, unscaledLetterHeight / 2); asynchMeshGroups.Add(new MeshGroup(textMesh)); PlatingMeshGroupData newMeshInfo = new PlatingMeshGroupData(); newMeshInfo.spacing = printer.GetOffsetLeftOfCharacterIndex(i); asynchPlatingDatas.Add(newMeshInfo); asynchMeshGroupTransforms.Add(ScaleRotateTranslate.Identity()); PlatingHelper.CreateITraceableForMeshGroup(asynchPlatingDatas, asynchMeshGroups, newIndex, null); ScaleRotateTranslate moved = asynchMeshGroupTransforms[newIndex]; moved.translation *= Matrix4X4.CreateTranslation(new Vector3(0, 0, unscaledLetterHeight / 2)); asynchMeshGroupTransforms[newIndex] = moved; newIndex++; } processingProgressControl.PercentComplete = ((i + 1) * 95 / currentText.Length); } }
public override Task Rebuild() { this.DebugDepth("Rebuild"); var rebuildLock = RebuildLock(); return(Task.Run(() => { using (new CenterAndHeightMaintainer(this)) { bool valuesChanged = false; var height = Height.ClampIfNotCalculated(this, .01, 1000000, ref valuesChanged); var nameToWrite = NameToWrite.Value(this); if (string.IsNullOrWhiteSpace(nameToWrite)) { Mesh = PlatonicSolids.CreateCube(20, 10, height); } else { Mesh = null; this.Children.Modify(list => { list.Clear(); var offest = 0.0; double pointsToMm = 0.352778; foreach (var letter in nameToWrite.ToCharArray()) { var style = new StyledTypeFace(ApplicationController.GetTypeFace(this.Font), PointSize.Value(this)); var letterPrinter = new TypeFacePrinter(letter.ToString(), style) { ResolutionScale = 10 }; var scaledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm)); list.Add(new Object3D() { Mesh = VertexSourceToMesh.Extrude(scaledLetterPrinter, this.Height.Value(this)), Matrix = Matrix4X4.CreateTranslation(offest, 0, 0), Name = letter.ToString() }); offest += letterPrinter.GetSize(letter.ToString()).X *pointsToMm; } }); } } UiThread.RunOnIdle(() => { rebuildLock.Dispose(); Invalidate(InvalidateType.DisplayValues); Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children)); }); })); }
public blur() { m_rbuf2 = new ImageBuffer(); m_shape_bounds = new RectangleDouble(); m_method = new RadioButtonGroup(new Vector2(10.0, 10.0), new Vector2(130.0, 60.0)); m_radius = new Slider(new Vector2(130 + 10.0, 10.0 + 4.0), new Vector2(290, 8.0)); m_shadow_ctrl = new PolygonEditWidget(4); m_channel_r = new CheckBox(10.0, 80.0, "Red"); m_channel_g = new CheckBox(10.0, 95.0, "Green"); m_channel_b = new CheckBox(10.0, 110.0, "Blue"); m_FlattenCurves = new CheckBox(10, 315, "Convert And Flatten Curves"); m_FlattenCurves.Checked = true; AddChild(m_method); m_method.AddRadioButton("Stack Blur"); m_method.AddRadioButton("Recursive Blur"); m_method.AddRadioButton("Channels"); m_method.SelectedIndex = 1; AddChild(m_radius); m_radius.SetRange(0.0, 40.0); m_radius.Value = 15.0; m_radius.Text = "Blur Radius={0:F2}"; AddChild(m_shadow_ctrl); AddChild(m_channel_r); AddChild(m_channel_g); AddChild(m_channel_b); AddChild(m_FlattenCurves); m_channel_g.Checked = true; m_sl = new ScanlineCachePacked8(); StyledTypeFace typeFaceForLargeA = new StyledTypeFace(LiberationSansFont.Instance, 300, flatenCurves: false); m_path = typeFaceForLargeA.GetGlyphForCharacter('a'); Affine shape_mtx = Affine.NewIdentity(); shape_mtx *= Affine.NewTranslation(150, 100); m_path = new VertexSourceApplyTransform(m_path, shape_mtx); m_shape = new FlattenCurves(m_path); bounding_rect.bounding_rect_single(m_shape, 0, ref m_shape_bounds); m_shadow_ctrl.SetXN(0, m_shape_bounds.Left); m_shadow_ctrl.SetYN(0, m_shape_bounds.Bottom); m_shadow_ctrl.SetXN(1, m_shape_bounds.Right); m_shadow_ctrl.SetYN(1, m_shape_bounds.Bottom); m_shadow_ctrl.SetXN(2, m_shape_bounds.Right); m_shadow_ctrl.SetYN(2, m_shape_bounds.Top); m_shadow_ctrl.SetXN(3, m_shape_bounds.Left); m_shadow_ctrl.SetYN(3, m_shape_bounds.Top); m_shadow_ctrl.line_color(new ColorF(0, 0.3, 0.5, 0.3)); }
public void CharacterBoundsTest() { // Validates character bounds computation from IVertexSource char[] sampleCharacters = "@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{}[]| !\"#$%&?'()*+,-./0123456789".ToCharArray(); int fontSize = 12; var typeface = new StyledTypeFace(LiberationSansFont.Instance, fontSize); string filename = $"{nameof(LiberationSansFont)}-{fontSize}.json"; string testDataPath = TestContext.CurrentContext.ResolveProjectPath(new string[] { "..", "..", "TestData", filename }); // Project sample string characters to dictionary with character bounds var characterBounds = sampleCharacters.ToDictionary(c => c, c => GetCharacterBounds(c, typeface)); var jsonSettings = new JsonSerializerSettings() { Converters = new List <JsonConverter>() { new FlatRectangleDoubleConverter() } }; // Update the control data if (false) { Directory.CreateDirectory(Path.GetDirectoryName(testDataPath)); File.WriteAllText( testDataPath, JsonConvert.SerializeObject(characterBounds, jsonSettings)); } // Load sample data string json = File.ReadAllText(testDataPath); var controlData = JsonConvert.DeserializeObject <Dictionary <char, RectangleDouble> >(json, jsonSettings); // Validate each character against previously computed control data foreach (var kvp in characterBounds) { Assert.IsTrue(controlData.ContainsKey(kvp.Key), "Expected key not found: " + kvp.Key); RectangleDouble actual = kvp.Value; RectangleDouble expected = controlData[kvp.Key]; Assert.AreEqual(expected.Left, actual.Left, 0.001, "Bounds Left differ"); Assert.AreEqual(expected.Bottom, actual.Bottom, 0.001, "Bounds Bottom differ"); Assert.AreEqual(expected.Right, actual.Right, 0.001, "Bounds Right differ"); Assert.AreEqual(expected.Top, actual.Top, 0.001, "Bounds Top differ"); Assert.AreEqual(expected, actual); } }
private void AddCharacterMeshes(string currentText, TypeFacePrinter printer) { int newIndex = asyncMeshGroups.Count; StyledTypeFace typeFace = printer.TypeFaceStyle; for (int i = 0; i < currentText.Length; i++) { string letter = currentText[i].ToString(); TypeFacePrinter letterPrinter = new TypeFacePrinter(letter, typeFace); if (CharacterHasMesh(letterPrinter, letter)) { #if true Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, unscaledLetterHeight / 2); #else Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, unscaledLetterHeight / 2); // this is the code to make rounded tops // convert the letterPrinter to clipper polygons List <List <IntPoint> > insetPoly = VertexSourceToPolygon.CreatePolygons(letterPrinter); // inset them ClipperOffset clipper = new ClipperOffset(); clipper.AddPaths(insetPoly, JoinType.jtMiter, EndType.etClosedPolygon); List <List <IntPoint> > solution = new List <List <IntPoint> >(); clipper.Execute(solution, 5.0); // convert them back into a vertex source // merge both the inset and original vertex sources together // convert the new vertex source into a mesh (trianglulate them) // offset the inner loop in z // create the polygons from the inner loop to a center point so that there is the rest of an approximation of the bubble // make the mesh for the bottom // add the top and bottom together // done #endif asyncMeshGroups.Add(new MeshGroup(textMesh)); PlatingMeshGroupData newMeshInfo = new PlatingMeshGroupData(); newMeshInfo.spacing = printer.GetOffsetLeftOfCharacterIndex(i); asyncPlatingDatas.Add(newMeshInfo); asyncMeshGroupTransforms.Add(ScaleRotateTranslate.Identity()); PlatingHelper.CreateITraceableForMeshGroup(asyncPlatingDatas, asyncMeshGroups, newIndex, null); ScaleRotateTranslate moved = asyncMeshGroupTransforms[newIndex]; moved.translation *= Matrix4X4.CreateTranslation(new Vector3(0, 0, unscaledLetterHeight / 2)); asyncMeshGroupTransforms[newIndex] = moved; newIndex++; } processingProgressControl.PercentComplete = ((i + 1) * 95 / currentText.Length); } }
public override void OnDraw(Graphics2D graphics2D) { #if DEBUG ExecutionTimer.Instance.Reset(); totalDrawTime.Restart(); #endif drawTimer.Start(); base.OnDraw(graphics2D); drawTimer.Stop(); #if DEBUG // this is to debug memory allocation and freeing totalDrawTime.Stop(); long memory = GC.GetTotalMemory(false); this.Title = string.Format("Allocated = {0:n0} : {1}ms, d{2} Size = {3}x{4}", memory, totalDrawTime.ElapsedMilliseconds, drawCount++, this.Width, this.Height); #if false if (timingWindow == null) { string staticDataPath = ApplicationDataStorage.Instance.ApplicationStaticDataPath; string fontPath = Path.Combine(staticDataPath, "Fonts", "LiberationMono.svg"); TypeFace boldTypeFace = TypeFace.LoadSVG(fontPath); typeFaceToUse = new StyledTypeFace(boldTypeFace, 12); timingWindow = new PerformanceFeedbackWindow(); } { if (totalDrawTime.Elapsed.TotalSeconds > .05) { timingWindow.ShowResults(totalDrawTime.Elapsed.TotalSeconds); } } #endif #endif if (firstDraw) { Parent.MinimumSize = new Vector2(590, 540); firstDraw = false; foreach (string arg in commandLineArgs) { if (Path.GetExtension(arg).ToUpper() == ".STL") { new PartPreviewMainWindow(new PrintItemWrapper(new DataStorage.PrintItem(Path.GetFileName(arg), Path.GetFullPath(arg)))); } } } }
public override void OnDraw(Graphics2D graphics2D) { GammaLookUpTable gamma = new GammaLookUpTable(gammaSlider.Value); IRecieveBlenderByte NormalBlender = new BlenderBGR(); IRecieveBlenderByte GammaBlender = new BlenderGammaBGR(gamma); ImageBuffer rasterNormal = new ImageBuffer(); rasterNormal.Attach(graphics2D.DestImage, NormalBlender); ImageBuffer rasterGamma = new ImageBuffer(); rasterGamma.Attach(graphics2D.DestImage, GammaBlender); ImageClippingProxy clippingProxyNormal = new ImageClippingProxy(rasterNormal); ImageClippingProxy clippingProxyGamma = new ImageClippingProxy(rasterGamma); clippingProxyNormal.clear(new RGBA_Floats(1, 1, 1)); ScanlineRasterizer ras = new ScanlineRasterizer(); scanline_unpacked_8 sl = new scanline_unpacked_8(); int size_mul = (int)pixelSizeSlider.Value; renderer_enlarged ren_en = new renderer_enlarged(size_mul); StyledTypeFace type = new StyledTypeFace(LiberationSansFont.Instance, 12); IVertexSource character = type.GetGlyphForCharacter('E'); character.rewind(0); ras.reset(); ras.add_path(character); ren_en.RenderSolid(clippingProxyGamma, ras, sl, RGBA_Bytes.Black); ScanlineRenderer scanlineRenderer = new ScanlineRenderer(); scanlineRenderer.RenderSolid(clippingProxyGamma, ras, sl, RGBA_Bytes.Black); ras.gamma(new gamma_none()); PathStorage ps = new PathStorage(); Stroke pg = new Stroke(ps); pg.width(2); DrawBigA(graphics2D); base.OnDraw(graphics2D); }
private void InsertTextDoWork(string currentText) { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; asynchMeshGroups.Clear(); asynchMeshGroupTransforms.Clear(); asynchPlatingDatas.Clear(); TypeFacePrinter brailPrinter = new TypeFacePrinter(currentText, new StyledTypeFace(brailTypeFace, 12)); int firstNewCharacter = 0; StyledTypeFace boldStyled = new StyledTypeFace(boldTypeFace, 12); if (includeText.Checked) { TypeFacePrinter normalPrinter = new TypeFacePrinter(currentText, boldStyled); Vector2 normalSize = normalPrinter.GetSize(); AddCharacterMeshes(currentText, normalPrinter); firstNewCharacter = asynchPlatingDatas.Count; } AddCharacterMeshes(currentText, brailPrinter); Vector2 brailSize = brailPrinter.GetSize(); for (int i = firstNewCharacter; i < asynchPlatingDatas.Count; i++) { asynchPlatingDatas[i].spacing = asynchPlatingDatas[i - firstNewCharacter].spacing + new Vector2(0, -boldStyled.CapHeightInPixels * 1.5); } CreateBase(asynchMeshGroups, asynchMeshGroupTransforms, asynchPlatingDatas); SetWordPositions(asynchMeshGroups, asynchMeshGroupTransforms, asynchPlatingDatas); SetWordSize(asynchMeshGroups, asynchMeshGroupTransforms); SetWordHeight(asynchMeshGroups, asynchMeshGroupTransforms); CenterTextOnScreen(asynchMeshGroups, asynchMeshGroupTransforms); processingProgressControl.PercentComplete = 95; }
// Behavior which relies on classic IVertexSource.vertex iteration private static RectangleDouble GetCharacterBounds(char character, StyledTypeFace typeface) { IVertexSource glyphForCharacter = typeface.GetGlyphForCharacter(character, 1); glyphForCharacter.rewind(0); ShapePath.FlagsAndCommand curCommand; var bounds = RectangleDouble.ZeroIntersection; do { curCommand = glyphForCharacter.vertex(out double x, out double y); if (curCommand != ShapePath.FlagsAndCommand.Stop && !ShapePath.is_close(curCommand)) { bounds.ExpandToInclude(x, y); } } while (curCommand != ShapePath.FlagsAndCommand.Stop); return(bounds); }
private void AddContent(HtmlParser htmlParser, string htmlContent) { ElementState elementState = htmlParser.CurrentElementState; string decodedHtml = HtmlParser.UrlDecode(htmlContent); switch (elementState.TypeName) { case "p": { elementsUnderConstruction.Push(new FlowLayoutWidget()); elementsUnderConstruction.Peek().Name = "p"; elementsUnderConstruction.Peek().HAnchor = HAnchor.ParentLeftRight; if (decodedHtml != null && decodedHtml != "") { WrappingTextWidget content = new WrappingTextWidget(decodedHtml, pointSize: elementState.PointSize, textColor: ActiveTheme.Instance.PrimaryTextColor); //content.VAnchor = VAnchor.ParentTop; elementsUnderConstruction.Peek().AddChild(content); } } break; case "div": { elementsUnderConstruction.Push(new FlowLayoutWidget()); elementsUnderConstruction.Peek().Name = "div"; if (decodedHtml != null && decodedHtml != "") { TextWidget content = new TextWidget(decodedHtml, pointSize: elementState.PointSize, textColor: ActiveTheme.Instance.PrimaryTextColor); elementsUnderConstruction.Peek().AddChild(content); } } break; case "!DOCTYPE": break; case "body": break; case "img": { ImageBuffer image = new ImageBuffer(elementState.SizeFixed.x, elementState.SizeFixed.y, 32, new BlenderBGRA()); ImageWidget_AsyncLoadOnDraw imageWidget = new ImageWidget_AsyncLoadOnDraw(image, elementState.src); // put the image into the widget when it is done downloading. if (elementsUnderConstruction.Peek().Name == "a") { Button linkButton = new Button(0, 0, imageWidget); linkButton.Cursor = Cursors.Hand; linkButton.Click += (sender, mouseEvent) => { MatterControlApplication.Instance.LaunchBrowser(elementState.Href); }; elementsUnderConstruction.Peek().AddChild(linkButton); } else { elementsUnderConstruction.Peek().AddChild(imageWidget); } } break; case "a": { elementsUnderConstruction.Push(new FlowLayoutWidget()); elementsUnderConstruction.Peek().Name = "a"; if (decodedHtml != null && decodedHtml != "") { Button linkButton = linkButtonFactory.Generate(decodedHtml); StyledTypeFace styled = new StyledTypeFace(LiberationSansFont.Instance, elementState.PointSize); double descentInPixels = styled.DescentInPixels; linkButton.OriginRelativeParent = new VectorMath.Vector2(linkButton.OriginRelativeParent.x, linkButton.OriginRelativeParent.y + descentInPixels); linkButton.Click += (sender, mouseEvent) => { MatterControlApplication.Instance.LaunchBrowser(elementState.Href); }; elementsUnderConstruction.Peek().AddChild(linkButton); } } break; case "table": break; case "td": case "span": GuiWidget widgetToAdd; if (elementState.Classes.Contains("translate")) { decodedHtml = decodedHtml.Localize(); } if (elementState.Classes.Contains("toUpper")) { decodedHtml = decodedHtml.ToUpper(); } if (elementState.Classes.Contains("versionNumber")) { decodedHtml = VersionInfo.Instance.ReleaseVersion; } if (elementState.Classes.Contains("buildNumber")) { decodedHtml = VersionInfo.Instance.BuildVersion; } Button createdButton = null; if (elementState.Classes.Contains("centeredButton")) { createdButton = textImageButtonFactory.Generate(decodedHtml); widgetToAdd = createdButton; } else if (elementState.Classes.Contains("linkButton")) { double oldFontSize = linkButtonFactory.fontSize; linkButtonFactory.fontSize = elementState.PointSize; createdButton = linkButtonFactory.Generate(decodedHtml); StyledTypeFace styled = new StyledTypeFace(LiberationSansFont.Instance, elementState.PointSize); double descentInPixels = styled.DescentInPixels; createdButton.OriginRelativeParent = new VectorMath.Vector2(createdButton.OriginRelativeParent.x, createdButton.OriginRelativeParent.y + descentInPixels); widgetToAdd = createdButton; linkButtonFactory.fontSize = oldFontSize; } else { TextWidget content = new TextWidget(decodedHtml, pointSize: elementState.PointSize, textColor: ActiveTheme.Instance.PrimaryTextColor); widgetToAdd = content; } if (createdButton != null) { if (elementState.Id == "sendFeedback") { createdButton.Click += (sender, mouseEvent) => { ContactFormWindow.Open(); }; } else if (elementState.Id == "clearCache") { createdButton.Click += (sender, mouseEvent) => { AboutWidget.DeleteCacheData(); }; } } if (elementState.VerticalAlignment == ElementState.VerticalAlignType.top) { widgetToAdd.VAnchor = VAnchor.ParentTop; } elementsUnderConstruction.Peek().AddChild(widgetToAdd); break; case "tr": elementsUnderConstruction.Push(new FlowLayoutWidget()); elementsUnderConstruction.Peek().Name = "tr"; if (elementState.SizePercent.y == 100) { elementsUnderConstruction.Peek().VAnchor = VAnchor.ParentBottomTop; } if (elementState.Alignment == ElementState.AlignType.center) { elementsUnderConstruction.Peek().HAnchor |= HAnchor.ParentCenter; } break; default: throw new NotImplementedException("Don't know what to do with '{0}'".FormatWith(elementState.TypeName)); } }
private void AddContent(HtmlParser htmlParser, string htmlContent) { ElementState elementState = htmlParser.CurrentElementState; string decodedHtml = HtmlParser.UrlDecode(htmlContent); switch (elementState.TypeName) { case "a": { Button linkButton = linkButtonFactory.Generate(decodedHtml); StyledTypeFace styled = new StyledTypeFace(LiberationSansFont.Instance, elementState.PointSize); double descentInPixels = styled.DescentInPixels; linkButton.OriginRelativeParent = new VectorMath.Vector2(linkButton.OriginRelativeParent.x, linkButton.OriginRelativeParent.y + descentInPixels); linkButton.Click += (sender, mouseEvent) => { MatterControlApplication.Instance.LaunchBrowser(elementState.Href); }; currentRow.AddChild(linkButton); } break; case "table": break; case "td": case "span": GuiWidget widgetToAdd; if (elementState.Classes.Contains("translate")) { decodedHtml = decodedHtml.Localize(); } if (elementState.Classes.Contains("toUpper")) { decodedHtml = decodedHtml.ToUpper(); } if (elementState.Classes.Contains("versionNumber")) { decodedHtml = VersionInfo.Instance.ReleaseVersion; } if (elementState.Classes.Contains("buildNumber")) { decodedHtml = VersionInfo.Instance.BuildVersion; } Button createdButton = null; if (elementState.Classes.Contains("centeredButton")) { createdButton = textImageButtonFactory.Generate(decodedHtml); widgetToAdd = createdButton; } else if (elementState.Classes.Contains("linkButton")) { double oldFontSize = linkButtonFactory.fontSize; linkButtonFactory.fontSize = elementState.PointSize; createdButton = linkButtonFactory.Generate(decodedHtml); StyledTypeFace styled = new StyledTypeFace(LiberationSansFont.Instance, elementState.PointSize); double descentInPixels = styled.DescentInPixels; createdButton.OriginRelativeParent = new VectorMath.Vector2(createdButton.OriginRelativeParent.x, createdButton.OriginRelativeParent.y + descentInPixels); widgetToAdd = createdButton; linkButtonFactory.fontSize = oldFontSize; } else { TextWidget content = new TextWidget(decodedHtml, pointSize: elementState.PointSize, textColor: ActiveTheme.Instance.PrimaryTextColor); widgetToAdd = content; } if (createdButton != null) { if (elementState.Id == "sendFeedback") { createdButton.Click += (sender, mouseEvent) => { ContactFormWindow.Open(); }; } else if (elementState.Id == "clearCache") { createdButton.Click += (sender, mouseEvent) => { DeleteCacheData(); }; } } if (elementState.VerticalAlignment == ElementState.VerticalAlignType.top) { widgetToAdd.VAnchor = VAnchor.ParentTop; } currentRow.AddChild(widgetToAdd); break; case "tr": currentRow = new FlowLayoutWidget(); if (elementState.HeightPercent == 100) { currentRow.VAnchor = VAnchor.ParentBottomTop; } if (elementState.Alignment == ElementState.AlignType.center) { currentRow.HAnchor |= HAnchor.ParentCenter; } break; default: throw new NotImplementedException("Don't know what to do with {0}".FormatWith(elementState.TypeName)); } }