Ejemplo n.º 1
0
        public GlyphImage CreateGlyphImage(GlyphPathBuilder builder, float pxscale)
        {
            _txToVxs.Reset();
            //1. builder read shape and translate it with _txToVxs
            builder.ReadShapes(_txToVxs);

            using (VxsTemp.Borrow(out var glyphVxs, out var vxs2))
            {
                //2. write translated data (in the _txToVxs) to glyphVxs

                _txToVxs.WriteOutput(glyphVxs, pxscale);

                RectD 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;

                    RectD bounds2 = vxs2.GetBoundingRect();
                    if (w < bounds2.Right)
                    {
                        w = (int)Math.Ceiling(bounds2.Right);
                    }
                    //
                    painter.UseSubPixelLcdEffect = true;
                    //we use white glyph on black bg for this texture
                    painter.Clear(Color.Black);
                    painter.FillColor = Color.White;
                    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.UseSubPixelLcdEffect = 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 GlyphImage(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.TextureOffsetX = (short)dx;
                glyphImage.TextureOffsetY = (short)dy;

                glyphImage.SetImageBuffer(MemBitmapExtensions.CopyImgBuffer(painter.RenderSurface.DestBitmap, w, h), false);
                //copy data from agg canvas to glyph image
                return(glyphImage);
            }
        }
Ejemplo n.º 2
0
        public GlyphImage CreateGlyphImage(GlyphPathBuilder builder, float pxscale)
        {
            //1. create

            var txToVxs = new GlyphTranslatorToVxs();

            builder.ReadShapes(txToVxs);
            //
            //create new one
            var glyphVxs = new VertexStore();

            txToVxs.WriteOutput(glyphVxs, pxscale);
            //find bound
            //--------------------------------------------
            //GlyphImage glyphImg = new GlyphImage()
            RectD bounds = RectD.ZeroIntersection;

            PixelFarm.CpuBlit.VertexProcessing.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;

            //
            dx = Math.Ceiling(dx); //since we need to move it, then move it with integer value
            dy = Math.Ceiling(dy); //since we need to move it, then move it with integer value

            //we need some borders
            int horizontal_margin = 1;                         //'margin' 1px
            int vertical_margin   = 1;                         //margin 1 px

            dx += horizontal_margin;                           //+ left margin
            dy += vertical_margin;                             //+ top margin
                                                               //--------------------------------------------
                                                               //create glyph img
            w = (int)Math.Ceiling(dx + w + horizontal_margin); //+right margin
            h = (int)Math.Ceiling(dy + h + vertical_margin);   //+bottom margin

            ActualBitmap img     = new ActualBitmap(w, h);
            AggPainter   painter = AggPainter.Create(img);

            if (TextureKind == TextureKind.StencilLcdEffect)
            {
                VertexStore vxs2 = new VertexStore();
                glyphVxs.TranslateToNewVxs(dx + 0.33f, dy, vxs2); //offset to proper x of subpixel rendering  ***
                glyphVxs = vxs2;
                //
                painter.UseSubPixelLcdEffect = true;

                //we use white glyph on black bg for this texture
                painter.Clear(Color.Black);
                painter.FillColor = Color.White;
                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
            {
                VertexStore vxs2 = new VertexStore();
                glyphVxs.TranslateToNewVxs(dx, dy, vxs2);
                glyphVxs = vxs2;

                painter.UseSubPixelLcdEffect = false;

                if (TextureKind == TextureKind.StencilGreyScale)
                {
                    painter.Clear(Color.Empty);
                    painter.FillColor = Color.Black;
                }
                else
                {
                    painter.Clear(BackGroundColor);
                    painter.FillColor = this.GlyphColor;
                }
                painter.Fill(glyphVxs);
            }
            //
            var glyphImage = new GlyphImage(w, h);

            glyphImage.TextureOffsetX = dx;
            glyphImage.TextureOffsetY = dy;
            glyphImage.SetImageBuffer(ActualBitmapExtensions.CopyImgBuffer(img, w), false);
            //copy data from agg canvas to glyph image
            return(glyphImage);
        }
Ejemplo n.º 3
0
        //template<class Scanline, class Ras>
        public void RenderGourand(Painter p)
        {
            float alpha = this.AlphaValue;
            float brc   = 1;

#if SourceDepth24
            pixfmt_alpha_blend_rgb pf = new pixfmt_alpha_blend_rgb(backBuffer, new blender_bgr());
#else
#endif
            ////var destImage = gx.DestImage;
            ////span_allocator span_alloc = new span_allocator();

            //specific for agg
            AggPainter painter = p as AggPainter;
            if (painter == null)
            {
                return;
            }

            //
            AggRenderSurface   aggRdsf        = painter.RenderSurface;
            SpanGenGouraudRGBA gouraudSpanGen = new SpanGenGouraudRGBA();
            aggRdsf.ScanlineRasterizer.ResetGamma(new GammaLinear(0.0f, this.LinearGamma));
            double d = this.DilationValue;
            // Six triangles

            double xc = (m_x[0] + m_x[1] + m_x[2]) / 3.0;
            double yc = (m_y[0] + m_y[1] + m_y[2]) / 3.0;
            double x1 = (m_x[1] + m_x[0]) / 2 - (xc - (m_x[1] + m_x[0]) / 2);
            double y1 = (m_y[1] + m_y[0]) / 2 - (yc - (m_y[1] + m_y[0]) / 2);
            double x2 = (m_x[2] + m_x[1]) / 2 - (xc - (m_x[2] + m_x[1]) / 2);
            double y2 = (m_y[2] + m_y[1]) / 2 - (yc - (m_y[2] + m_y[1]) / 2);
            double x3 = (m_x[0] + m_x[2]) / 2 - (xc - (m_x[0] + m_x[2]) / 2);
            double y3 = (m_y[0] + m_y[2]) / 2 - (yc - (m_y[0] + m_y[2]) / 2);
            gouraudSpanGen.SetColor(ColorEx.Make(1, 0, 0, alpha),
                                    ColorEx.Make(0, 1, 0, alpha),
                                    ColorEx.Make(brc, brc, brc, alpha));
            gouraudSpanGen.SetTriangle(m_x[0], m_y[0], m_x[1], m_y[1], xc, yc, d);

            var tmpVxs = _tmpVxs;
            painter.Fill(gouraudSpanGen.MakeVxs(tmpVxs), gouraudSpanGen);
            tmpVxs.Clear();
            gouraudSpanGen.SetColor(ColorEx.Make(0, 1, 0, alpha),
                                    ColorEx.Make(0, 0, 1, alpha),
                                    ColorEx.Make(brc, brc, brc, alpha));
            gouraudSpanGen.SetTriangle(m_x[1], m_y[1], m_x[2], m_y[2], xc, yc, d);
            painter.Fill(gouraudSpanGen.MakeVxs(tmpVxs), gouraudSpanGen);
            tmpVxs.Clear();
            gouraudSpanGen.SetColor(ColorEx.Make(0, 0, 1, alpha),
                                    ColorEx.Make(1, 0, 0, alpha),
                                    ColorEx.Make(brc, brc, brc, alpha));
            gouraudSpanGen.SetTriangle(m_x[2], m_y[2], m_x[0], m_y[0], xc, yc, d);
            painter.Fill(gouraudSpanGen.MakeVxs(tmpVxs), gouraudSpanGen);
            tmpVxs.Clear();
            brc = 1 - brc;
            gouraudSpanGen.SetColor(ColorEx.Make(1, 0, 0, alpha),
                                    ColorEx.Make(0, 1, 0, alpha),
                                    ColorEx.Make(brc, brc, brc, alpha));
            gouraudSpanGen.SetTriangle(m_x[0], m_y[0], m_x[1], m_y[1], x1, y1, d);
            painter.Fill(gouraudSpanGen.MakeVxs(tmpVxs), gouraudSpanGen);
            tmpVxs.Clear();
            gouraudSpanGen.SetColor(ColorEx.Make(0, 1, 0, alpha),
                                    ColorEx.Make(0, 0, 1, alpha),
                                    ColorEx.Make(brc, brc, brc, alpha));
            gouraudSpanGen.SetTriangle(m_x[1], m_y[1], m_x[2], m_y[2], x2, y2, d);
            painter.Fill(gouraudSpanGen.MakeVxs(tmpVxs), gouraudSpanGen);
            tmpVxs.Clear();
            gouraudSpanGen.SetColor(ColorEx.Make(0, 0, 1, alpha),
                                    ColorEx.Make(1, 0, 0, alpha),
                                    ColorEx.Make(brc, brc, brc, alpha));
            gouraudSpanGen.SetTriangle(m_x[2], m_y[2], m_x[0], m_y[0], x3, y3, d);
            painter.Fill(gouraudSpanGen.MakeVxs(tmpVxs), gouraudSpanGen);
            tmpVxs.Clear();
        }
Ejemplo n.º 4
0
        //template<class Scanline, class Ras>
        public void RenderGourand(Painter p)
        {
            float alpha = this.AlphaValue;
            float brc   = 1;

#if SourceDepth24
            pixfmt_alpha_blend_rgb pf = new pixfmt_alpha_blend_rgb(backBuffer, new blender_bgr());
#else
#endif
            ////var destImage = gx.DestImage;
            ////span_allocator span_alloc = new span_allocator();

            //specific for agg
            AggPainter painter = p as AggPainter;
            if (painter == null)
            {
                return;
            }

            //
            AggRenderSurface      aggsx          = painter.RenderSurface;
            RGBAGouraudSpanGen    gouraudSpanGen = new RGBAGouraudSpanGen();
            GouraudVerticeBuilder grBuilder      = new GouraudVerticeBuilder();

            aggsx.ScanlineRasterizer.ResetGamma(new GammaLinear(0.0f, this.LinearGamma));

            grBuilder.DilationValue = (float)this.DilationValue;
            // Six triangles

            double xc = (_x[0] + _x[1] + _x[2]) / 3.0;
            double yc = (_y[0] + _y[1] + _y[2]) / 3.0;
            double x1 = (_x[1] + _x[0]) / 2 - (xc - (_x[1] + _x[0]) / 2);
            double y1 = (_y[1] + _y[0]) / 2 - (yc - (_y[1] + _y[0]) / 2);
            double x2 = (_x[2] + _x[1]) / 2 - (xc - (_x[2] + _x[1]) / 2);
            double y2 = (_y[2] + _y[1]) / 2 - (yc - (_y[2] + _y[1]) / 2);
            double x3 = (_x[0] + _x[2]) / 2 - (xc - (_x[0] + _x[2]) / 2);
            double y3 = (_y[0] + _y[2]) / 2 - (yc - (_y[0] + _y[2]) / 2);
            grBuilder.SetColor(ColorEx.Make(1, 0, 0, alpha),
                               ColorEx.Make(0, 1, 0, alpha),
                               ColorEx.Make(brc, brc, brc, alpha));
            grBuilder.SetTriangle(_x[0], _y[0], _x[1], _y[1], xc, yc);

            GouraudVerticeBuilder.CoordAndColor c0, c1, c2;
            grBuilder.GetArrangedVertices(out c0, out c1, out c2);
            gouraudSpanGen.SetColorAndCoords(c0, c1, c2);

            using (Tools.BorrowVxs(out var v1))
            {
                painter.Fill(grBuilder.MakeVxs(v1), gouraudSpanGen);
                v1.Clear();

                //
                grBuilder.SetColor(
                    ColorEx.Make(0, 1, 0, alpha),
                    ColorEx.Make(0, 0, 1, alpha),
                    ColorEx.Make(brc, brc, brc, alpha));
                grBuilder.SetTriangle(_x[1], _y[1], _x[2], _y[2], xc, yc);
                grBuilder.GetArrangedVertices(out c0, out c1, out c2);
                gouraudSpanGen.SetColorAndCoords(c0, c1, c2);

                painter.Fill(grBuilder.MakeVxs(v1), gouraudSpanGen);
                v1.Clear();

                //
                grBuilder.SetColor(ColorEx.Make(0, 0, 1, alpha),
                                   ColorEx.Make(1, 0, 0, alpha),
                                   ColorEx.Make(brc, brc, brc, alpha));
                grBuilder.SetTriangle(_x[2], _y[2], _x[0], _y[0], xc, yc);
                grBuilder.GetArrangedVertices(out c0, out c1, out c2);
                gouraudSpanGen.SetColorAndCoords(c0, c1, c2);
                painter.Fill(grBuilder.MakeVxs(v1), gouraudSpanGen);
                v1.Clear();
                //
                brc = 1 - brc;
                grBuilder.SetColor(ColorEx.Make(1, 0, 0, alpha),
                                   ColorEx.Make(0, 1, 0, alpha),
                                   ColorEx.Make(brc, brc, brc, alpha));
                grBuilder.SetTriangle(_x[0], _y[0], _x[1], _y[1], x1, y1);
                grBuilder.GetArrangedVertices(out c0, out c1, out c2);
                gouraudSpanGen.SetColorAndCoords(c0, c1, c2);
                painter.Fill(grBuilder.MakeVxs(v1), gouraudSpanGen);
                v1.Clear();

                grBuilder.SetColor(ColorEx.Make(0, 1, 0, alpha),
                                   ColorEx.Make(0, 0, 1, alpha),
                                   ColorEx.Make(brc, brc, brc, alpha));
                grBuilder.SetTriangle(_x[1], _y[1], _x[2], _y[2], x2, y2);
                grBuilder.GetArrangedVertices(out c0, out c1, out c2);
                gouraudSpanGen.SetColorAndCoords(c0, c1, c2);
                painter.Fill(grBuilder.MakeVxs(v1), gouraudSpanGen);
                v1.Clear();
                //
                grBuilder.SetColor(ColorEx.Make(0, 0, 1, alpha),
                                   ColorEx.Make(1, 0, 0, alpha),
                                   ColorEx.Make(brc, brc, brc, alpha));
                grBuilder.SetTriangle(_x[2], _y[2], _x[0], _y[0], x3, y3);
                grBuilder.GetArrangedVertices(out c0, out c1, out c2);
                gouraudSpanGen.SetColorAndCoords(c0, c1, c2);
                painter.Fill(grBuilder.MakeVxs(v1), gouraudSpanGen);
                v1.Clear();
            }
        }
Ejemplo n.º 5
0
        static Vertex2d ConvToV2d(PointD p) => new Vertex2d(p.X, p.Y); //temp

        /// <summary>
        /// fill inner and outer border from corner0 to corner1
        /// </summary>
        /// <param name="painter"></param>
        /// <param name="c0"></param>
        /// <param name="c1"></param>
        void FillBorders(AggPainter painter, ContourCorner c0, ContourCorner c1)
        {
            //counter-clockwise

            if (!c0.MiddlePoint_IsTouchPoint)
            {
                return;
            }

            //with a given corner, have have information of 3 points
            //left-point of the corner,=> from vertex
            //middle-point, current vertex
            //right-point,=> next vertex
            //a vertex may be touch-curve vertext, or 'not-touch-curve' vertex

            //'is not touch-curve point', => this vertex is a  control point of C3 or C4 curve,
            //-------------------------------------------------------

            if (c0.RightPoint_IsTouchPoint)
            {
                //c0 => touch curve
                //c1 => touch curve,
                //we create an imaginary line from  c0 to c1
                //then we create an 'inner border' of a line from c0 to c1
                //and we create an 'outer border' of a line from c0 to c1
                //
                using (Tools.BorrowVxs(out var v1))
                {
                    //1. inner-border, set fill mode to inform proper color encoding of inner border
                    _msdfEdgePxBlender.FillMode = MsdfEdgePixelBlender.BlenderFillMode.InnerBorder;



                    //2020-03-13, version 3 fill is still better than v3.1,
                    //TODO: review version v3.1


                    if (_use_v3_1)
                    {
                        //version 3.1 fill technique
                        CreateBorder(v1, ConvToV2d(c1.RightPoint), ConvToV2d(c1.MiddlePoint), ConvToV2d(c0.MiddlePoint), ConvToV2d(c0.LeftPoint));
                    }
                    else
                    {
                        //version 3 fill technique
                        CreateInnerBorder(v1,
                                          c0.MiddlePoint.X, c0.MiddlePoint.Y,
                                          c1.MiddlePoint.X, c1.MiddlePoint.Y, INNER_BORDER_W);
                    }

                    painter.Fill(v1, c0.InnerColor);
                    //-------------
                    v1.Clear(); //reuse
                                //2. outer-border, set fill mode too.


                    _msdfEdgePxBlender.FillMode = MsdfEdgePixelBlender.BlenderFillMode.OuterBorder;

                    if (_use_v3_1)
                    {
                        //version 3.1 fill technique
                        CreateBorder(v1, ConvToV2d(c0.LeftPoint), ConvToV2d(c0.MiddlePoint), ConvToV2d(c1.MiddlePoint), ConvToV2d(c1.RightPoint));
                    }
                    else
                    {
                        //version 3 fill technique
                        CreateOuterBorder(v1,
                                          c0.MiddlePoint.X, c0.MiddlePoint.Y,
                                          c1.MiddlePoint.X, c1.MiddlePoint.Y, OUTER_BORDER_W);
                    }


                    painter.Fill(v1, c0.OuterColor);
                }
            }
            else
            {
                //painter.CurrentBxtBlendOp = null;

                //**
                //c0 is touch line,
                //but c1 is not, this means=> next segment will be a curve(C3 or C4 curve)
                //
                EdgeSegment ownerSeg = c1.CenterSegment;

                switch (ownerSeg.SegmentKind)
                {
                default: throw new NotSupportedException();

                case EdgeSegmentKind.CubicSegment:
                {
                    //approximate
                    CubicSegment cs = (CubicSegment)ownerSeg;
                    using (Tools.BorrowVxs(out var v1))
                        using (Tools.BorrowShapeBuilder(out var b))
                            using (Tools.BorrowStroke(out var strk))
                            {
                                b.MoveTo(cs.P0.x + _dx, cs.P0.y + _dy) //...
                                .Curve4To(cs.P1.x + _dx, cs.P1.y + _dy,
                                          cs.P2.x + _dx, cs.P2.y + _dy,
                                          cs.P3.x + _dx, cs.P3.y + _dy)
                                .NoMore()
                                .Flatten();


                                //-----------------------
                                //fill outside part of the curve
                                strk.Width = CURVE_STROKE_EACHSIDE * 2;
                                strk.StrokeSideForOpenShape = StrokeSideForOpenShape.Outside;
                                strk.MakeVxs(b.CurrentSharedVxs, v1);

                                painter.Fill(v1, c0.OuterColor);
                                //-----------------------
                                //fill inside part of the curve
                                v1.Clear(); //reuse
                                strk.StrokeSideForOpenShape = StrokeSideForOpenShape.Inside;
                                strk.MakeVxs(b.CurrentSharedVxs, v1);
                                painter.Fill(v1, c0.InnerColor);
                                //-----------------------
                            }
                }
                break;

                case EdgeSegmentKind.QuadraticSegment:
                {
                    QuadraticSegment qs = (QuadraticSegment)ownerSeg;

                    using (Tools.BorrowVxs(out var v1))
                        using (Tools.BorrowShapeBuilder(out var b))
                            using (Tools.BorrowStroke(out var strk))
                            {
                                b.MoveTo(qs.P0.x + _dx, qs.P0.y + _dy)//...
                                .Curve3To(qs.P1.x + _dx, qs.P1.y + _dy,
                                          qs.P2.x + _dx, qs.P2.y + _dy)
                                .NoMore()
                                .Flatten();

                                //-----------------------
                                //fill outside part of the curve
                                strk.Width = CURVE_STROKE_EACHSIDE * 2;
                                strk.StrokeSideForOpenShape = StrokeSideForOpenShape.Outside;
                                strk.MakeVxs(b.CurrentSharedVxs, v1);
                                painter.Fill(v1, c0.OuterColor);
                                //-----------------------
                                //fill inside part of the curve
                                v1.Clear();//reuse
                                strk.StrokeSideForOpenShape = StrokeSideForOpenShape.Inside;
                                strk.MakeVxs(b.CurrentSharedVxs, v1);
                                painter.Fill(v1, c0.InnerColor);
                                //-----------------------
                            }
                }
                break;
                }
            }
        }