VertexStore BuildVxsForGlyph(GlyphOutlineBuilder builder, char character, float size) { //----------- //TODO: review here builder.Build(character, size); var txToVxs = new GlyphTranslatorToVxs(); builder.ReadShapes(txToVxs); VertexStore v2 = new VertexStore(); using (Tools.BorrowVxs(out var v0)) using (Tools.BorrowCurveFlattener(out var flattener)) { txToVxs.WriteOutput(v0); Q1RectD bounds = v0.GetBoundingRect(); AffineMat mat = AffineMat.Iden(); mat.Scale(1, -1);//flipY mat.Translate(0, bounds.Height); flattener.MakeVxs(v0, mat, v2); } return(v2); }
public override Rectangle GetRectBounds() { if (!_evalRectBounds) { // Q1RectD bound1 = BoundingRect.GetBoundingRect(_vxs); _bounds = new Rectangle( (int)Math.Round(bound1.Left), (int)Math.Round(bound1.Bottom), //*** (int)Math.Round(bound1.Width), (int)Math.Round(bound1.Height)); _evalRectBounds = true; } return(_bounds); }
private void button2_Click(object sender, EventArgs e) { //EXAMPLE, low-level //this show how to render a glyph on screen //read font file LoadFont(); //inside a font //get some glyph by its name //Glyph oneGlyph = _latinModernMathFont.GetGlyphByName("one"); //for get glyph by name ushort glyphIndex = _latinModernMathFont.GetGlyphIndex((int)'1'); //a glyph contains coordinates of line and curves //we transform data inside it to vxs //this is done by GlyphContour builder GlyphTranslatorToVxs glyphTxToVxs = new GlyphTranslatorToVxs(); GlyphOutlineBuilder outlineBuilder = new GlyphOutlineBuilder(_latinModernMathFont); outlineBuilder.BuildFromGlyphIndex(glyphIndex, 20); //read data into outline builder outlineBuilder.ReadShapes(glyphTxToVxs); //translate data inside outline builder to vxs using (Tools.BorrowVxs(out var v1, out var v2)) using (Tools.BorrowAggPainter(_memBmp, out var p)) { glyphTxToVxs.WriteOutput(v1); //original v1 is head-down Q1RectD bounds = v1.GetBoundingRect(); //with this bounds you also know glyph width/height //we want head up, so => flip it AffineMat aff = AffineMat.Iden(); aff.Translate(-bounds.Width / 2, -bounds.Height / 2); aff.Scale(1, -1); aff.Translate(bounds.Width / 2, bounds.Height / 2); aff.TransformToVxs(v1, v2); //copy data //now the glyph data is inside v1 //test paint this glyph p.Clear(PixelFarm.Drawing.Color.White); p.Fill(v2, PixelFarm.Drawing.Color.Black); } //----------- CopyBitmapToScreen(); }
public static void ReverseClockDirection(this VertexStore src, VertexStore outputVxs) { //temp fix for reverse clock direction Q1RectD bounds = src.GetBoundingRect(); double centerX = (bounds.Left + bounds.Width) / 2; double centerY = (bounds.Top + bounds.Height) / 2; //Affine aff = Affine.New(AffinePlan.Translate(-centerX, -centerY), // AffinePlan.Scale(1, -1),//flipY, // AffinePlan.Translate(centerX, centerY)); AffineMat aff = AffineMat.Iden(); aff.Translate(-centerX, -centerY); aff.Translate(1, -1);//flipY aff.Translate(centerX, centerY); aff.TransformToVxs(src, outputVxs); }
public static VgVisualElement CreateVgVisualElementFromGlyph(string actualFontFile, float sizeInPts, char c) { if (!s_loadedTypefaces.TryGetValue(actualFontFile, out Typography.OpenFont.Typeface typeface)) { //create vgrender vx from font-glyph // using (System.IO.FileStream fs = new FileStream(actualFontFile, FileMode.Open)) { Typography.OpenFont.OpenFontReader reader = new Typography.OpenFont.OpenFontReader(); typeface = reader.Read(fs); } } if (_glyphMaskStore == null) { _glyphMaskStore = new Typography.OpenFont.Contours.GlyphMeshStore(); _glyphMaskStore.FlipGlyphUpward = true; } _glyphMaskStore.SetFont(typeface, sizeInPts); //----------------- VertexStore vxs = _glyphMaskStore.GetGlyphMesh(typeface.GetGlyphIndex(c)); var spec = new SvgPathSpec() { FillColor = Color.Red }; VgVisualDoc renderRoot = new VgVisualDoc(); VgVisualElement renderE = new VgVisualElement(WellknownSvgElementName.Path, spec, renderRoot); //offset the original vxs to (0,0) bounds //PixelFarm.CpuBlit.RectD bounds = vxs.GetBoundingRect(); //Affine translate = Affine.NewTranslation(-bounds.Left, -bounds.Bottom); //renderE._vxsPath = vxs.CreateTrim(translate); Q1RectD bounds = vxs.GetBoundingRect(); Affine translate = Affine.NewTranslation(-bounds.Left, -bounds.Bottom); renderE.VxsPath = vxs.CreateTrim(translate); return(renderE); }
public BitmapAtlasItemSource CreateAtlasItem(GlyphOutlineBuilder builder, float pxscale) { _txToVxs.Reset(); //1. builder read shape and translate it with _txToVxs builder.ReadShapes(_txToVxs); using (Tools.BorrowVxs(out var glyphVxs, out var vxs2)) { //2. write translated data (in the _txToVxs) to glyphVxs _txToVxs.WriteOutput(glyphVxs, pxscale); Q1RectD bounds = glyphVxs.GetBoundingRect(); //-------------------------------------------- int w = (int)System.Math.Ceiling(bounds.Width); int h = (int)System.Math.Ceiling(bounds.Height); if (w < 5) { w = 5; } if (h < 5) { h = 5; } //we need some margin int horizontal_margin = 1; int vertical_margin = 1; //translate to positive quadrant and use minimum space int dx = (int)Math.Ceiling((bounds.Left < 0) ? -bounds.Left : 0); int dy = 0; //vertical adjust =>since we need to move it, then move it with integer value if (bounds.Bottom < 0) { dy = (int)Math.Ceiling(-bounds.Bottom); } else if (bounds.Bottom > 0) { dy = (int)Math.Floor(-bounds.Bottom); } dx += horizontal_margin; //margin left dy += vertical_margin; //-------------------------------------------- w = dx + w + horizontal_margin; //+right margin h = vertical_margin + h + vertical_margin; //+bottom margin AggPainter painter = Painter; if (TextureKind == TextureKind.StencilLcdEffect) { glyphVxs.TranslateToNewVxs(dx + 0.33f, dy, vxs2); //offset to proper x of subpixel rendering *** glyphVxs = vxs2; Q1RectD bounds2 = vxs2.GetBoundingRect(); if (w < bounds2.Right) { w = (int)Math.Ceiling(bounds2.Right); } // painter.UseLcdEffectSubPixelRendering = true; //we use white glyph on black bg for this texture painter.Clear(Color.Black); painter.FillColor = Color.White; //painter.Clear(Color.FromArgb(0, 255, 255, 255)); //white -transparent //painter.FillColor = Color.Black; //painter.Clear(Color.White); //painter.FillColor = Color.Black; //painter.Clear(Color.Empty); //painter.FillColor = Color.Black; painter.Fill(glyphVxs); //apply sharpen filter //painter.DoFilter(new RectInt(0, h, w, 0), 2); //painter.DoFilter(new RectInt(0, h, w, 0), 2); //? } else { glyphVxs.TranslateToNewVxs(dx, dy, vxs2); glyphVxs = vxs2; painter.UseLcdEffectSubPixelRendering = false; if (TextureKind == TextureKind.StencilGreyScale) { painter.Clear(Color.Empty); painter.FillColor = Color.Black; } else { painter.Clear(BackGroundColor); painter.FillColor = this.GlyphColor; } painter.Fill(glyphVxs); } // if (w > painter.RenderSurface.DestBitmap.Width) { w = painter.RenderSurface.DestBitmap.Width; } if (h > painter.RenderSurface.DestBitmap.Height) { h = painter.RenderSurface.DestBitmap.Height; } var glyphImage = new BitmapAtlasItemSource(w, h); #if DEBUG if (dx < short.MinValue || dx > short.MaxValue) { throw new NotSupportedException(); } if (dy < short.MinValue || dy > short.MaxValue) { throw new NotSupportedException(); } #endif glyphImage.TextureXOffset = (short)dx; glyphImage.TextureYOffset = (short)dy; glyphImage.SetImageBuffer(MemBitmapExt.CopyImgBuffer(painter.RenderSurface.DestBitmap, w, h), false); //copy data from agg canvas to glyph image return(glyphImage); } }
GlyphBitmap GetGlyphBitmapFromColorOutlineGlyph(ushort glyphIndex, GlyphMeshStore glyphMeshStore, ushort colorLayerStart) { //not found=> create a newone Typography.OpenFont.Tables.COLR _colrTable = _typeface.COLRTable; Typography.OpenFont.Tables.CPAL _cpalTable = _typeface.CPALTable; Q1RectD totalBounds = Q1RectD.ZeroIntersection(); { //calculate bounds of this glyph ushort colorLayerCount = _colrTable.LayerCounts[glyphIndex]; for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { BoundingRect.GetBoundingRect(glyphMeshStore.GetGlyphMesh(_colrTable.GlyphLayers[c]), ref totalBounds); } } //dbugExportCount++; var memBmp = new MemBitmap((int)Math.Round(totalBounds.Width), (int)Math.Round(totalBounds.Height));//??? int offset_x = 0; int offset_y = 0; using (Tools.BorrowAggPainter(memBmp, out AggPainter painter)) { painter.Clear(Color.Transparent); painter.SetOrigin(0, 0); offset_x = -(int)(totalBounds.Left); offset_y = -(int)(totalBounds.Bottom); ushort colorLayerCount = _colrTable.LayerCounts[glyphIndex]; int palette = 0; // FIXME: assume palette 0 for now for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { _cpalTable.GetColor( _cpalTable.Palettes[palette] + _colrTable.GlyphPalettes[c], //index out byte r, out byte g, out byte b, out byte a); ushort gIndex = _colrTable.GlyphLayers[c]; VertexStore vxs = glyphMeshStore.GetGlyphMesh(gIndex); using (Tools.BorrowVxs(out var v1)) { vxs.TranslateToNewVxs(offset_x, offset_y, v1); painter.FillColor = new Color(r, g, b);//? a component painter.Fill(v1); } } //find ex #if DEBUG //memBmp.SaveImage("a0x" + (dbugExportCount) + ".png"); #endif } return(new GlyphBitmap { Bitmap = memBmp, Width = memBmp.Width, Height = memBmp.Height, ImageStartX = -offset_x, //offset back ImageStartY = -offset_y //offset back }); }
public void UpdateBounds() { _vgVisElem.InvalidateBounds(); _boundingRect = _vgVisElem.GetRectBounds(); }