public IEnumerable <NoForms.Common.Rectangle> HitTextRange(int start, int length, NoForms.Common.Point offset, UText text) { // Grab a ref to the sdgtextinfo var ti = glyphRunner.GetTextInfo(text); return(glyphRunner.HitTextRange(ti, start, length, offset)); }
// FIXME another example of type switching. Cant put d2d code on other side of bridge in eg UGeometryBase abstraction // and also, using a factory to create the UGeometryBase will make d2d specific versions. // IDEA This is possible: Use factory (DI?) and check the Uxxx instances when passed to this type of class, and recreate // a portion of the Uxxx if it doesnt match D2D? Factory could be configured for d2d/ogl etc. This links in with cacheing // code too? Not sure if this will static compile :/ thats kinda the point... we'd need the Uxxx.ICreateStuff to be a specific // D2D interface...could subclass... would check if(ICreateStuff is D2DCreator) as d2dcreator else Icreatestuff=new d2dcreator... void AppendGeometry(ref GraphicsPath path, UGeometryBase geo, NoForms.Common.Point start) // ref GraphicsPath will allow us to recreate it if we want with new. { if (geo is UArcBase) { System.Drawing.PointF[] pts; if (geo is UArc) { UArc arc = geo as UArc; pts = (geo.Retreive <SDGDraw>(() => { var elInput = new GeometryLib.Ellipse_Input(start.X, start.Y, arc.endPoint.X, arc.endPoint.Y, arc.arcSize.width, arc.arcSize.height, arc.rotation); var elSolution = new List <GeometryLib.Ellipse_Output>(GeometryLib.Ellipse.Get_X0Y0(elInput)).ToArray(); GeometryLib.Ellipse.SampleArc(elInput, elSolution, arc.reflex, arc.sweepClockwise, arc.resolution, out pts); return(new disParr(pts)); }) as disParr).pts; } //else if (geo is UEasyArc) //{ // var arc = geo as UEasyArc; // pts = (geo.Retreive<SDGDraw>(() => // { // return new disParr(new List<System.Drawing.PointF>(EllipseLib.EasyEllipse.Generate(new EllipseLib.EasyEllipse.EasyEllipseInput() // { // rotation = arc.rotation, // start_x = start.X, // start_y = start.Y, // rx = arc.arcSize.width, // ry = arc.arcSize.height, // t1 = arc.startAngle, // t2 = arc.endAngle, // resolution = arc.resolution // })).ToArray()); // }) as disParr).pts; //} else { throw new NotImplementedException(); } // clone the data List <PointF> opts = new List <PointF>(path.PointCount > 0 ? path.PathPoints : new PointF[0]); List <byte> otyps = new List <byte>(path.PointCount > 0 ? path.PathTypes : new byte[0]); // do the types if (otyps.Count == 0 || otyps[otyps.Count - 1] != (byte)PathPointType.Start) { otyps.Add((byte)PathPointType.Start); opts.Add(SDGTr.trF(start)); } for (int i = 0; i < pts.Length; i++) { otyps.Add((byte)PathPointType.Line); // try to interpolate a bit? } // append new data opts.AddRange(pts); // Replace the path via reference path = new GraphicsPath(opts.ToArray(), otyps.ToArray(), path.FillMode); } else if (geo is ULine) { ULine line = geo as ULine; path.AddLine(SDGTr.trF(start), SDGTr.trF(line.endPoint)); } else if (geo is UBeizer) { UBeizer beizer = geo as UBeizer; path.AddBezier(SDGTr.trF(start), SDGTr.trF(beizer.controlPoint1), SDGTr.trF(beizer.controlPoint2), SDGTr.trF(beizer.endPoint)); } else { throw new NotImplementedException(); } }
public void DrawEllipse(NoForms.Common.Point center, float radiusX, float radiusY, UBrush brush, UStroke stroke) { realRenderer.graphics.DrawEllipse(CreatePen(brush, stroke), center.X - radiusX, center.Y - radiusY, radiusX * 2, radiusY * 2); }
public void DrawLine(NoForms.Common.Point start, NoForms.Common.Point end, UBrush brush, UStroke stroke) { realRenderer.graphics.DrawLine(CreatePen(brush, stroke), SDGTr.trF(start), SDGTr.trF(end)); }
public void FillEllipse(NoForms.Common.Point center, float radiusX, float radiusY, UBrush brush) { realRenderer.graphics.FillEllipse(CreateBrush(brush), center.X - radiusX, center.Y - radiusY, radiusX * 2, radiusY * 2); }
public IEnumerable <NoForms.Common.Rectangle> HitTextRange(UTextGlyphingInfo ti, int start, int length, NoForms.Common.Point offset) { int cc = 0; foreach (var glyph in ti.glyphRuns) { // stride through glyphruns that are not involved. if (cc + glyph.run.runLength <= start) { cc += glyph.run.runLength; continue; } float cx = 0; foreach (var gchar in glyph.run.charSizes) { // end iteration when we fall past this bound if (cc >= start + length) { yield break; } // calculate and yield the current char rect yield return(new NoForms.Common.Rectangle(glyph.location.X + cx, glyph.location.Y + (glyph.run.runSize.height - gchar.height), gchar.width, gchar.height)); // inc counters for following glyphs cx += gchar.width; } } }
public IEnumerable <NoForms.Common.Rectangle> HitTextRange(int start, int length, NoForms.Common.Point offset, UText text) { var ti = GetTextData(text); return(glyphRunner.HitTextRange(ti.tinfo, start, length, offset)); }
public UTextHitInfo HitPoint(NoForms.Common.Point hitPoint, UText text) { var ti = GetTextData(text); return(glyphRunner.HitPoint(ti.tinfo, hitPoint)); }
public void DrawText(UText textObject, NoForms.Common.Point location, UBrush defBrush, UTextDrawOptions opt, bool clientRendering) { GLTextStore <sdg.Font> GLds = GetTextData(textObject); //when uninitialised, all members wll be null/-1. we need to run a pass of the generator thing if (GLds.texture_for_blitting == -1) { var tl = GLds.tinfo = glyphRunner.GetTextInfo(textObject); float l = float.MaxValue, t = float.MaxValue, b = float.MinValue, r = float.MinValue; // if empty if (tl.glyphRuns.Count == 0) { return; } // Calculate the render rectangle foreach (var gr in tl.glyphRuns) { var p1 = gr.location; var p2 = new Point(p1.X + gr.run.runSize.width, p1.Y + gr.run.runSize.height); if (p1.X < l) { l = p1.X; } if (p2.X < l) { l = p2.X; } if (p1.Y < t) { t = p1.Y; } if (p2.Y < t) { t = p2.Y; } if (p2.X > r) { r = p2.X; } if (p1.X > r) { r = p1.X; } if (p2.Y > b) { b = p2.Y; } if (p1.Y > b) { b = p1.Y; } } Rectangle rrect = new Rectangle(new Point(l, t), new Point(r, b), true); System.Diagnostics.Debug.Assert(rrect.width > 0 && rrect.height > 0); // ensure we have the software buffer EnsureStoredData(textObject, new Size(r - l, b - t)); // we will draw black onto transparent background, and handle brushes when rendering to blitting texture GLds.renderOffset = new Point(l, t); GLds.sbb_context.Clear(sdg.Color.Transparent); foreach (var glyphrun in tl.glyphRuns) { var style = glyphrun.run.drawStyle; UFont font = style != null ? (style.fontOverride ?? textObject.font) : textObject.font; sdg.FontStyle fs = (font.bold ? sdg.FontStyle.Bold : 0) | (font.italic ? sdg.FontStyle.Italic : 0); var sdgFont = FTR(font); // render at 0,0 because we cropped to the minimum drawing area of glyphs... GLds.sbb_context.DrawString(glyphrun.run.content, sdgFont, sdg.Brushes.Black, PTR(glyphrun.location - GLds.renderOffset), sdg.StringFormat.GenericTypographic); } // now copy into the blit mask GLds.texture_for_blitting = GL.GenTexture(); LoadBitmapIntoTexture(GLds.texture_for_blitting, GLds.softbitbuf); } // draw background... foreach (var glyphrun in GLds.tinfo.glyphRuns) { var style = glyphrun.run.drawStyle; UBrush brsh = style != null ? (style.fgOverride ?? defBrush) : defBrush; if (style != null && style.bgOverride != null) { FillRectangle(new NoForms.Common.Rectangle(location + glyphrun.location + GLds.renderOffset, glyphrun.run.runSize), style.bgOverride); } } // use blit mask to create a blitting texture, using the Util fbo (FIXME? but no multithreads...) //throw new NotImplementedException(); // blit the buffer (FIXME thats not blitting) FIXME needs seperate (what about masked tezture alpbas!) var gs = GLds.softbitbuf.Size; Rectangle rr = new Rectangle(location + GLds.renderOffset, new Size(gs.Width, gs.Height)); int st = rel.renderData.sofwareBuffer.Count; bufferTexRect(rr, new Rectangle(0, 0, 1, 1)); int cnt = rel.renderData.sofwareBuffer.Count - st; rel.renderData.bufferInfo.Add(new RenderInfo(st, cnt, ArrayData.Vertex | ArrayData.Color | ArrayData.Texture, PrimitiveType.Quads, GLds.texture_for_blitting)); }