public static SpriteTextureMapData <PixelFarm.CpuBlit.MemBitmap> CreateMsdfImage(ExtMsdfGen.Shape shape, MsdfGenParams genParams, EdgeBmpLut lutBuffer = null) { double left = MAX; double bottom = MAX; double right = -MAX; double top = -MAX; shape.findBounds(ref left, ref bottom, ref right, ref top); int w = (int)Math.Ceiling((right - left)); int h = (int)Math.Ceiling((top - bottom)); if (w < genParams.minImgWidth) { w = genParams.minImgWidth; } if (h < genParams.minImgHeight) { h = genParams.minImgHeight; } //temp, for debug with glyph 'I', tahoma font //double edgeThreshold = 1.00000001;//default, if edgeThreshold < 0 then set edgeThreshold=1 //Msdfgen.Vector2 scale = new Msdfgen.Vector2(0.98714652956298199, 0.98714652956298199); //double pxRange = 4; //translate = new Msdfgen.Vector2(12.552083333333332, 4.0520833333333330); //double range = pxRange / Math.Min(scale.x, scale.y); int borderW = (int)((float)w / 5f) + 3; //org //var translate = new ExtMsdfgen.Vector2(left < 0 ? -left + borderW : borderW, bottom < 0 ? -bottom + borderW : borderW); //test var translate = new Vector2(-left + borderW, -bottom + borderW); w += borderW * 2; //borders,left- right h += borderW * 2; //borders, top- bottom double edgeThreshold = genParams.edgeThreshold; if (edgeThreshold < 0) { edgeThreshold = 1.00000001; //use default if edgeThreshold <0 } var scale = new Vector2(genParams.scaleX, genParams.scaleY); //scale double range = genParams.pxRange / Math.Min(scale.x, scale.y); //--------- FloatRGBBmp frgbBmp = new FloatRGBBmp(w, h); EdgeColoring.edgeColoringSimple(shape, genParams.angleThreshold); if (lutBuffer != null) { MsdfGenerator.generateMSDF2(frgbBmp, shape, range, scale, translate,//translate to positive quadrant edgeThreshold, lutBuffer); } else { MsdfGenerator.generateMSDF(frgbBmp, shape, range, scale, translate,//translate to positive quadrant edgeThreshold); } var spriteData = new SpriteTextureMapData <PixelFarm.CpuBlit.MemBitmap>(0, 0, w, h); spriteData.Source = PixelFarm.CpuBlit.MemBitmap.CreateFromCopy(w, h, MsdfGenerator.ConvertToIntBmp(frgbBmp)); spriteData.TextureXOffset = (float)translate.x; spriteData.TextureYOffset = (float)translate.y; return(spriteData); }
unsafe void CustomBlendPixel32(int *dstPtr, Color srcColor) { if (FillMode == BlenderFillMode.Force) { *dstPtr = srcColor.ToARGB(); return; } //------------------------------------------------------------- int srcColorABGR = (int)srcColor.ToABGR(); int existingColor = *dstPtr; //int existing_R = (existingColor >> CO.R_SHIFT) & 0xFF; int existing_G = (existingColor >> CO.G_SHIFT) & 0xFF; //int existing_B = (existingColor >> CO.B_SHIFT) & 0xFF; if (FillMode == BlenderFillMode.InnerAreaX) { //special mode if (existing_G == EdgeBmpLut.AREA_INSIDE_COVERAGE50 || existing_G == EdgeBmpLut.AREA_INSIDE_COVERAGE100) { *dstPtr = srcColor.ToARGB(); } return; } else { } if (existingColor == BLACK) { *dstPtr = srcColor.ToARGB(); return; } if (existingColor == _areaInside100) { *dstPtr = srcColor.ToARGB(); return; } if (srcColorABGR == existingColor) { return; } if (FillMode == BlenderFillMode.InnerArea50) { *dstPtr = srcColor.ToARGB(); return; } if (FillMode == BlenderFillMode.FinalFill) { if (existing_G == EdgeBmpLut.AREA_INSIDE_COVERAGEX || existing_G == EdgeBmpLut.AREA_INSIDE_COVERAGE50 || existing_G == EdgeBmpLut.AREA_INSIDE_COVERAGE100 || existing_G == EdgeBmpLut.BORDER_OVERLAP_INSIDE || existing_G == EdgeBmpLut.BORDER_INSIDE) { *dstPtr = srcColor.ToARGB(); } return; } //------------------------------------------------------------- //decode edge information //we use 2 bytes for encode edge number ushort existingEdgeNo = EdgeBmpLut.DecodeEdgeFromColor(existingColor, out AreaKind existingAreaKind); ushort newEdgeNo = EdgeBmpLut.DecodeEdgeFromColor(srcColor, out AreaKind newEdgeAreaKind); //if (existingAreaKind == AreaKind.AreaInsideCoverage100) //{ // //*dstPtr = srcColor.ToARGB(); // return; //} //if (existingAreaKind == AreaKind.AreaInsideCoverage100) //{ // switch (newEdgeAreaKind) // { // case AreaKind.BorderOutside: // case AreaKind.OverlapOutside: // return; // case AreaKind.AreaInsideCoverage100: // return; // case AreaKind.OverlapInside: // return; // default: // { // } // break; // } //} #if DEBUG if (existingEdgeNo == 389) { } #endif //if (FillMode == BlenderFillMode.FinalFill) //{ // if (existingAreaKind == AreaKind.BorderOutside || existingAreaKind == AreaKind.OverlapOutside) // { // *dstPtr = srcColor.ToARGB(); // } // return; //} if (newEdgeAreaKind == AreaKind.OverlapInside || newEdgeAreaKind == AreaKind.OverlapOutside) { //new color is overlap color if (existingAreaKind == AreaKind.OverlapInside || existingAreaKind == AreaKind.OverlapOutside) { CornerList registerList = _overlapList[newEdgeNo]; _overlapList[existingEdgeNo].Append(registerList); } else { CornerList registerList = _overlapList[newEdgeNo]; registerList.Append(existingEdgeNo); *dstPtr = EdgeBmpLut.EncodeToColor(newEdgeNo, (existing_G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside).ToARGB(); } } else { if (existingAreaKind == AreaKind.OverlapInside || existingAreaKind == AreaKind.OverlapOutside) { _overlapList[existingEdgeNo].Append(newEdgeNo); } else { ////create new overlap part if (newEdgeNo == existingEdgeNo) { return; } OverlapPart overlapPart; AreaKind areaKind; if (existingAreaKind == AreaKind.BorderInside || existingAreaKind == AreaKind.AreaInsideCoverage100) { if (newEdgeAreaKind == AreaKind.BorderInside) { areaKind = AreaKind.OverlapInside; overlapPart = new OverlapPart( existingEdgeNo, (existing_G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside, newEdgeNo, (srcColor.G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside); } else { areaKind = AreaKind.OverlapInside; overlapPart = new OverlapPart( existingEdgeNo, (existing_G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside, newEdgeNo, (existing_G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside); } } else { //existing is outside if (newEdgeAreaKind == AreaKind.BorderInside) { areaKind = AreaKind.OverlapInside; overlapPart = new OverlapPart( existingEdgeNo, (existing_G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside, newEdgeNo, (existing_G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside); } else { areaKind = AreaKind.OverlapOutside; overlapPart = new OverlapPart( existingEdgeNo, (existing_G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside, newEdgeNo, (srcColor.G == EdgeBmpLut.BORDER_INSIDE) ? AreaKind.OverlapInside : AreaKind.OverlapOutside); } } //if (existingEdgeNo == 0) //{ // if (existingAreaKind == AreaKind.AreaInsideCoverage100) // { // *dstPtr = EdgeBmpLut.EncodeToColor(newEdgeNo, newEdgeAreaKind).ToARGB(); // return; // } //} //else //{ //} if (!_overlapParts.TryGetValue(overlapPart, out ushort found)) { if (_overlapList.Count >= ushort.MaxValue) { throw new NotSupportedException(); } // ushort newPartNo = (ushort)_overlapList.Count; _overlapParts.Add(overlapPart, newPartNo); // CornerList cornerList = new CornerList(); #if DEBUG if (_overlapList.Count >= 388) { } #endif _overlapList.Add(cornerList); cornerList.Append(existingEdgeNo); cornerList.Append(newEdgeNo); //set new color *dstPtr = EdgeBmpLut.EncodeToColor(newPartNo, areaKind).ToARGB(); } else { //set new color *dstPtr = EdgeBmpLut.EncodeToColor(found, areaKind).ToARGB(); } } } }