public void ApplyTransform(Agg.Transform.Affine tx) { int elemCount = _svgRenderVx.SvgVxCount; for (int i = 0; i < elemCount; ++i) { _svgRenderVx.SetInnerVx(i, SvgPart.TransformToNew(_svgRenderVx.GetInnerVx(i), tx)); } }
static SimpleFontAtlasBuilder CreateAggSubPixelRenderingTextureFont( Typeface typeface, float sizeInPoint, HintTechnique hintTech, IEnumerable <ushort> glyphIndexIter) { ////read type face from file //Typeface typeface; //using (var fs = new FileStream(fontfile, FileMode.Open, FileAccess.Read)) //{ // var reader = new OpenFontReader(); // //1. read typeface from font file // typeface = reader.Read(fs); //} //sample: create sample msdf texture //------------------------------------------------------------- var builder = new GlyphPathBuilder(typeface); builder.SetHintTechnique(hintTech); //------------------------------------------------------------- var atlasBuilder = new SimpleFontAtlasBuilder(); atlasBuilder.SetAtlasInfo(TextureKind.AggSubPixel, sizeInPoint); VertexStorePool vxsPool = new VertexStorePool(); //create agg cavnas foreach (ushort gindex in glyphIndexIter) { //build glyph builder.BuildFromGlyphIndex(gindex, sizeInPoint); var txToVxs = new GlyphTranslatorToVxs(); builder.ReadShapes(txToVxs); // //create new one var glyphVxs = new VertexStore(); txToVxs.WriteOutput(glyphVxs, vxsPool); //find bound //-------------------------------------------- //GlyphImage glyphImg = new GlyphImage() RectD bounds = new Agg.RectD(); BoundingRect.GetBoundingRect(new VertexStoreSnap(glyphVxs), ref bounds); //-------------------------------------------- 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; } //translate to positive quadrant double dx = (bounds.Left < 0) ? -bounds.Left : 0; double dy = (bounds.Bottom < 0) ? -bounds.Bottom : 0; w = w * 4; if (dx != 0 || dy != 0) { Agg.Transform.Affine transformMat = Agg.Transform.Affine.NewTranslation(dx, dy); VertexStore vxs2 = new VertexStore(); glyphVxs.TranslateToNewVxs(dx, dy, vxs2); glyphVxs = vxs2; } //-------------------------------------------- //create glyph img ActualImage img = new Agg.ActualImage(w, h, PixelFormat.ARGB32); ImageGraphics2D imgCanvas2d = new Agg.ImageGraphics2D(img); AggCanvasPainter painter = new Agg.AggCanvasPainter(imgCanvas2d); //we use white glyph on black bg for this texture painter.Clear(Color.Black); //fill with black painter.FillColor = Color.White; painter.StrokeColor = Color.White; //-------------------------------------------- painter.UseSubPixelRendering = true; //-------------------------------------------- //-------------------------------------------- painter.Fill(glyphVxs); //-------------------------------------------- var glyphImage = new GlyphImage(w, h); glyphImage.TextureOffsetX = dx; glyphImage.TextureOffsetY = dy; glyphImage.SetImageBuffer(ActualImage.GetBuffer2(img), false); //copy data from agg canvas to glyph image atlasBuilder.AddGlyph(gindex, glyphImage); //int[] buffer = glyphImage.GetImageBuffer(); //using (var bmp = new System.Drawing.Bitmap(glyphImage.Width, glyphImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImage.Width, glyphImage.Height), // System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a001_subpix_xn2_" + gindex + ".png"); //} } //var glyphImg2 = atlasBuilder.BuildSingleImage(); //using (var bmp = new System.Drawing.Bitmap(glyphImg2.Width, glyphImg2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg2.Width, glyphImg2.Height), // System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // int[] intBuffer = glyphImg2.GetImageBuffer(); // System.Runtime.InteropServices.Marshal.Copy(intBuffer, 0, bmpdata.Scan0, intBuffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a_total.png"); //} //atlasBuilder.SaveFontInfo("d:\\WImageTest\\a_info.xml"); return(atlasBuilder); }
public override void DrawFromGlyphPlans(UnscaledGlyphPlanList glyphPlanList, int startAt, int len, float x, float y) { Painter painter = this.TargetCanvasPainter; if (StartDrawOnLeftTop) { //version 2 //offset y down y += this.FontLineSpacingPx; } //Typeface typeface = _glyphPathBuilder.Typeface; //3. layout glyphs with selected layout technique //TODO: review this again, we should use pixel? float fontSizePoint = this.FontSizeInPoints; float scale = _currentTypeface.CalculateScaleToPixelFromPointSize(fontSizePoint); //4. render each glyph float ox = painter.OriginX; float oy = painter.OriginY; int endBefore = startAt + len; Typography.OpenFont.Tables.COLR colrTable = _currentTypeface.COLRTable; Typography.OpenFont.Tables.CPAL cpalTable = _currentTypeface.CPALTable; bool hasColorGlyphs = (colrTable != null) && (cpalTable != null); //--------------------------------------------------- _glyphMeshStore.SetFont(_currentTypeface, fontSizePoint); //--------------------------------------------------- float g_x = 0; float g_y = 0; float baseY = (int)y; if (!hasColorGlyphs) { bool savedUseLcdMode = painter.UseSubPixelLcdEffect; //save,restore later RenderQualtity savedRederQuality = painter.RenderQuality; painter.RenderQuality = RenderQualtity.HighQuality; painter.UseSubPixelLcdEffect = true; Agg.Transform.Affine flipY = Agg.Transform.Affine.NewMatix( Agg.Transform.AffinePlan.Scale(1, -1)); //flip Y VertexStore reusableVxs = new VertexStore(); float acc_x = 0; //acummulate x float acc_y = 0; //acummulate y for (int i = startAt; i < endBefore; ++i) { //----------------------------------- //TODO: review here *** //PERFORMANCE revisit here //if we have create a vxs we can cache it for later use? //----------------------------------- UnscaledGlyphPlan glyphPlan = glyphPlanList[i]; float ngx = acc_x + (float)Math.Round(glyphPlan.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyphPlan.OffsetY * scale); acc_x += (float)Math.Round(glyphPlan.AdvanceX * scale); g_x = ngx; g_y = ngy; painter.SetOrigin(g_x, g_y); //----------------------------------- //invert each glyph //version 3: reusableVxs.Clear(); VertexStore vxs = _glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex); flipY.TransformToVxs(vxs, reusableVxs); painter.Fill(reusableVxs); //version2; //VertexStore vsx = _glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex); //_vxs1 = _invertY.TransformToVxs(vsx, _vxs1); //painter.Fill(_vxs1); //_vxs1.Clear(); //version1 //painter.Fill(_glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex)); } //restore painter.RenderQuality = savedRederQuality; painter.UseSubPixelLcdEffect = savedUseLcdMode; } else { //------------- //this glyph has color information //------------- Color originalFillColor = painter.FillColor; float acc_x = 0; float acc_y = 0; for (int i = startAt; i < endBefore; ++i) { UnscaledGlyphPlan glyphPlan = glyphPlanList[i]; float ngx = acc_x + (float)Math.Round(glyphPlan.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyphPlan.OffsetY * scale); g_x = ngx; g_y = ngy; acc_x += (float)Math.Round(glyphPlan.AdvanceX * scale); painter.SetOrigin(g_x, g_y); //----------------------------------- ushort colorLayerStart; if (colrTable.LayerIndices.TryGetValue(glyphPlan.glyphIndex, out colorLayerStart)) { //TODO: optimize this //we found color info for this glyph ushort colorLayerCount = colrTable.LayerCounts[glyphPlan.glyphIndex]; byte r, g, b, a; for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { ushort gIndex = colrTable.GlyphLayers[c]; int palette = 0; // FIXME: assume palette 0 for now cpalTable.GetColor( cpalTable.Palettes[palette] + colrTable.GlyphPalettes[c], //index out r, out g, out b, out a); //----------- painter.FillColor = new Color(r, g, b);//? a component painter.Fill(_glyphMeshStore.GetGlyphMesh(gIndex)); } } else { //----------------------------------- //TODO: review here *** //PERFORMANCE revisit here //if we have create a vxs we can cache it for later use? //----------------------------------- painter.Fill(_glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex)); } } painter.FillColor = originalFillColor; //restore color } //restore prev origin painter.SetOrigin(ox, oy); }