public override void Draw(Painter p) { AggPainter painter = p as AggPainter; if (painter == null) { return; } // painter.Clear(Color.White); int width = painter.Width; int height = painter.Height; //change value *** if (_isMaskSliderValueChanged) { SetupMaskPixelBlender(width, height); _isMaskSliderValueChanged = false; // //painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlender; //change to new blender painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlenderPerCompo; //change to new blender } //1. alpha mask... //p2.DrawImage(alphaBitmap, 0, 0); //2. painter.FillColor = Color.Black; painter.FillRect(0, 0, 200, 100); //3. painter.FillColor = Color.Blue; painter.FillCircle(300, 300, 100); painter.DrawImage(lionImg, 20, 20); ////4. //painter.FillColor = Color.Black; ////this test lcd-effect => we need to draw it 3 times with different color component, on the same position ////(same as we do with OpenGLES rendering surface) //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; //painter.FillRect(0, 0, 200, 100); //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; //painter.FillRect(0, 0, 200, 100); //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; //painter.FillRect(0, 0, 200, 100); }
void RenderWithMsdfImg(Typeface typeface, char testChar, float sizeInPoint) { _painter.FillColor = PixelFarm.Drawing.Color.Black; //p.UseSubPixelRendering = chkLcdTechnique.Checked; _painter.Clear(PixelFarm.Drawing.Color.White); //---------------------------------------------------- var builder = new GlyphPathBuilder(typeface); builder.SetHintTechnique(_glyphRenderOptions.HintTechnique); //---------------------------------------------------- builder.Build(testChar, sizeInPoint); //---------------------------------------------------- var glyphToContour = new GlyphContourBuilder(); var msdfGenPars = new MsdfGenParams(); builder.ReadShapes(glyphToContour); //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours()); MsdfGenParams genParams = new MsdfGenParams(); GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, genParams); MemBitmap actualImg = MemBitmap.CreateFromCopy(glyphImg.Width, glyphImg.Height, glyphImg.GetImageBuffer()); _painter.DrawImage(actualImg, 0, 0); //using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new Rectangle(0, 0, w, h), 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_xn2_" + n + ".png"); //} if (_contourAnalysisOpts.ShowGrid) { //render grid RenderGrids(800, 600, _gridSize, _painter); } //6. use this util to copy image from Agg actual image to System.Drawing.Bitmap PixelFarm.CpuBlit.Imaging.BitmapHelper.CopyToGdiPlusBitmapSameSize(_destImg, _winBmp); //--------------- //7. just render our bitmap _g.Clear(Color.White); _g.DrawImage(_winBmp, new Point(30, 20)); }
public override void Draw(Painter p) { AggPainter painter = p as AggPainter; if (painter == null) { return; } painter.Clear(Color.White); switch (FilterName) { case FilterName.Unknown: painter.RenderSurface.CustomImgSpanGen = null; break; case FilterName.NearestNeighbor: painter.RenderSurface.CustomImgSpanGen = _imgSpanGenNN; break; default: DrawWeightDistributionGraph(p, _lut.WeightArray); painter.RenderSurface.CustomImgSpanGen = _imgSpanGenCustom; break; } VertexProcessing.AffinePlan[] p1 = new VertexProcessing.AffinePlan[] { VertexProcessing.AffinePlan.Translate(-_imgW / 2.0, -_imgH / 2.0), VertexProcessing.AffinePlan.RotateDeg(_rotationDeg), VertexProcessing.AffinePlan.Translate(_imgW / 2.0, _imgH / 2.0), }; p.DrawImage(_orgImg, p1); if (_thumbnailScaleDown > 0 && _thumbnailScaleDown < 1) { using (MemBitmap thumbnail = _orgImg.CreateThumbnailWithSuperSamplingTechnique(_thumbnailScaleDown)) { painter.DrawImage(thumbnail, 400, 300); } } base.Draw(p); }
public void BuildMultiFontSize(string multiFontSizeAtlasFilename, string imgOutputFilename) { //merge to the new one //1. ensure same atlas width int atlasW = 0; int j = _atlasList.Count; int totalHeight = 0; const int interAtlasSpace = 2; for (int i = 0; i < j; ++i) { TempMergingAtlasInfo atlasInfo = _atlasList[i]; SimpleBitmapAtlas fontAtlas = atlasInfo.fontAtlasFile.AtlasList[0]; totalHeight += fontAtlas.Height + interAtlasSpace; if (i == 0) { atlasW = fontAtlas.Width; } else { if (atlasW != fontAtlas.Width) { throw new NotSupportedException(); } } } //-------------------------------------------- //in this version, the glyph offsetY is measure from bottom*** int[] offsetFromBottoms = new int[j]; int offsetFromBottom = interAtlasSpace;//start offset for (int i = j - 1; i >= 0; --i) { TempMergingAtlasInfo atlasInfo = _atlasList[i]; SimpleBitmapAtlas fontAtlas = atlasInfo.fontAtlasFile.AtlasList[0]; offsetFromBottoms[i] = offsetFromBottom; offsetFromBottom += fontAtlas.Height + interAtlasSpace; } //-------------------------------------------- //merge all img to one int top = 0; using (MemBitmap memBitmap = new MemBitmap(atlasW, totalHeight)) { AggPainter painter = AggPainter.Create(memBitmap); for (int i = 0; i < j; ++i) { TempMergingAtlasInfo atlasInfo = _atlasList[i]; BitmapAtlasFile atlasFile = atlasInfo.fontAtlasFile; SimpleBitmapAtlas fontAtlas = atlasInfo.fontAtlasFile.AtlasList[0]; atlasInfo.NewCloneLocations = SimpleBitmapAtlas.CloneLocationWithOffset(fontAtlas, 0, offsetFromBottoms[i]); atlasInfo.ImgUrlDict = fontAtlas.ImgUrlDict; using (Stream fontImgStream = PixelFarm.Platforms.StorageService.Provider.ReadDataStream(atlasInfo.imgFile)) using (MemBitmap atlasBmp = MemBitmapExt.LoadBitmap(fontImgStream)) { painter.DrawImage(atlasBmp, 0, top); top += atlasBmp.Height + interAtlasSpace; } } memBitmap.SaveImage(imgOutputFilename); } //-------------------------------------------- //save merged font atlas //TODO: use 'File' provider to access system file using (FileStream fs = new FileStream(multiFontSizeAtlasFilename, FileMode.Create)) using (BinaryWriter w = new BinaryWriter(fs)) { //----------- //overview //total img info BitmapAtlasFile fontAtlasFile = new BitmapAtlasFile(); fontAtlasFile.StartWrite(fs); //1. simple atlas count fontAtlasFile.WriteOverviewMultiSizeFontInfo((ushort)j); //2. for (int i = 0; i < j; ++i) { TempMergingAtlasInfo atlasInfo = _atlasList[i]; RequestFont reqFont = atlasInfo.reqFont; fontAtlasFile.WriteOverviewFontInfo(reqFont.Name, reqFont.GetReqKey(), reqFont.SizeInPoints);//size in points fontAtlasFile.WriteTotalImageInfo( (ushort)atlasW, (ushort)top, 4, atlasInfo.textureKind); // fontAtlasFile.WriteAtlasItems(atlasInfo.NewCloneLocations); if (atlasInfo.ImgUrlDict != null) { fontAtlasFile.WriteImgUrlDict(atlasInfo.ImgUrlDict); } } fontAtlasFile.EndWrite(); } }
public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y) { AggPainter painter = p as AggPainter; if (painter == null) { return; } // int width = painter.Width; int height = painter.Height; if (!_pixelBlenderSetup) { SetupMaskPixelBlender(width, height); _pixelBlenderSetup = true; } int j = buffer.Length; //create temp buffer span that describe the part of a whole char buffer TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font); float scale = 1;// _fontAtlas.TargetTextureScale; int recommendLineSpacing = (int)_font.LineSpacingInPixels; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again y -= _font.LineSpacingInPixels; // float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; float gx = 0; float gy = 0; int baseY = (int)Math.Round(y); float acc_x = 0; float acc_y = 0; int lineHeight = (int)_font.LineSpacingInPixels;//temp //painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlenderPerCompo; //change to new blender painter.DestBitmapBlender.OutputPixelBlender = _maskPixelBlenderPerCompo; //change to new blender int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- gx = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x gy = (float)(y + (ngy - glyphData.TextureYOffset - srcH + lineHeight) * scaleFromTexture); acc_x += (float)Math.Round(glyph.AdvanceX * scale); gy = (float)Math.Floor(gy) + lineHeight; //clear with solid black color //_maskBufferPainter.Clear(Color.Black); _maskBufferPainter.FillRect(gx - 1, gy - 1, srcW + 2, srcH + 2, Color.Black); //draw 'stencil' glyph on mask-buffer _maskBufferPainter.DrawImage(_fontBmp, gx, gy, srcX, _fontBmp.Height - (srcY), srcW, srcH); //select component to render this need to render 3 times for lcd technique //1. B _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; painter.FillRect(gx + 1, gy, srcW, srcH); //2. G _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; painter.FillRect(gx + 1, gy, srcW, srcH); //3. R _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; painter.FillRect(gx + 1, gy, srcW, srcH); } }
public override void DrawFromGlyphPlans(GlyphPlanSequence glyphPlanSeq, int startAt, int len, float left, float top) { Typeface typeface = _textServices.ResolveTypeface(_font); float scale = typeface.CalculateScaleToPixelFromPointSize(_font.SizeInPoints); int recommendLineSpacing = (int)_font.LineSpacingInPixels; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again // TextureKind textureKind = _fontAtlas.TextureKind; float gx = 0; float gy = 0; int baseY = (int)Math.Round(top); float acc_x = 0; float acc_y = 0; int lineHeight = (int)_font.LineSpacingInPixels; //temp PixelBlender32 prevPxBlender = _painter.DestBitmapBlender.OutputPixelBlender; //save _painter.DestBitmapBlender.OutputPixelBlender = _maskPixelBlenderPerCompo; //change to new blender bool fillGlyphByGlyph = true; if (fillGlyphByGlyph) { //test... //fill glyph-by-glyh var aaTech = this.AntialiasTech; int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan unscaledGlyphPlan = glyphPlanSeq[i]; TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(unscaledGlyphPlan.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(unscaledGlyphPlan.OffsetX * scale); float ngy = acc_y + (float)Math.Round(unscaledGlyphPlan.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- //if (glyphData.TextureXOffset != 0) //{ //} gx = (float)(left + (ngx - glyphData.TextureXOffset)); //ideal x gy = (float)(top + (ngy + glyphData.TextureYOffset - srcH + lineHeight)); acc_x += (float)Math.Round(unscaledGlyphPlan.AdvanceX * scale); gy = (float)Math.Floor(gy);// + lineHeight; //clear with solid black color //_maskBufferPainter.Clear(Color.Black); //clear mask buffer at specific pos _maskBufferPainter.FillRect(gx - 1, gy - 1, srcW + 2, srcH + 2, Color.Black); //draw 'stencil' glyph on mask-buffer _maskBufferPainter.DrawImage(_fontBmp, gx, gy, srcX, _fontBmp.Height - (srcY + srcH), srcW, srcH); switch (aaTech) { default: { //select component to render this need to render 3 times for lcd technique //1. B _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; _painter.FillRect(gx + 1, gy, srcW, srcH); //2. G _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; _painter.FillRect(gx + 1, gy, srcW, srcH); //3. R _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; _painter.FillRect(gx + 1, gy, srcW, srcH); } break; case AntialiasTechnique.GreyscaleStencil: { //fill once //we choose greeh channel (middle) _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.EnableAll; _painter.FillRect(gx + 1, gy, srcW, srcH); } break; } } } else { //clear entire line _maskBufferPainter.FillRect(gx - 1, gy - 1, _maskBufferPainter.Width - gx + 2, lineHeight + 2, Color.Black); bool isFirst = true; int startX = 0, startY = 0; float lenW = 0; float lenH = 0; int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- gx = (float)(left + (ngx - glyphData.TextureXOffset)); //ideal x gy = (float)(top + (ngy - glyphData.TextureYOffset - srcH + lineHeight)); acc_x += (float)Math.Round(glyph.AdvanceX * scale); gy = (float)Math.Floor(gy) + lineHeight; if (isFirst) { startX = (int)gx; startY = (int)gy; isFirst = false; } _maskBufferPainter.DrawImage(_fontBmp, gx + 1, gy, srcX, _fontBmp.Height - (srcY), srcW + 1, srcH); lenW = gx + srcW; if (srcH > lenH) { lenH = srcH; } } //-------------------------- //fill color on 'stencil' mask { //select component to render this need to render 3 times for lcd technique //1. B _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; _painter.FillRect(startX + 1, startY, lenW, lenH); //2. G _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; _painter.FillRect(startX + 1, startY, lenW, lenH); //3. R _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; _painter.FillRect(startX + 1, startY, lenW, lenH); } } // _painter.DestBitmapBlender.OutputPixelBlender = prevPxBlender;//restore back }