Exemple #1
0
        private ActiveEdge CreateActiveEdge(Edge edge, int offX, float startPoint)
        {
            var z = new ActiveEdge(); // TODO: make a pool of these!!!

            float dxdy = (edge.x1 - edge.x0) / (edge.y1 - edge.y0);

            //STBTT_assert(e->y0 <= start_point);

            // round dx down to avoid going too far
            if (dxdy < 0)
            {
                z.dx = -(int)Math.Floor(FIX * -dxdy);
            }
            else
            {
                z.dx = (int)Math.Floor(FIX * dxdy);
            }

            z.x    = (int)Math.Floor(FIX * (edge.x0 + dxdy * (startPoint - edge.y0)));
            z.x   -= offX * FIX;
            z.ey   = edge.y1;
            z.next = null;

            if (edge.invert)
            {
                z.valid = 1;
            }
            else
            {
                z.valid = -1;
            }

            return(z);
        }
Exemple #2
0
        // note: this routine clips fills that extend off the edges...
        // ideally this wouldn't happen, but it could happen if the truetype glyph bounding boxes are wrong, or if the user supplies a too-small bitmap
        private void FillActiveEdges(byte[] scanline, int len, ActiveEdge e, int max_weight)
        {
            // non-zero winding fill
            int x0 = 0;
            int w  = 0;

            int x1;

            while (e != null)
            {
                if (w == 0)
                {
                    // if we're currently at zero, we need to record the edge start point
                    x0 = e.x;
                    w += e.valid;
                }
                else
                {
                    x1 = e.x;
                    w += e.valid;
                    // if we went to zero, we need to draw
                    if (w == 0)
                    {
                        int i = x0 >> FIXSHIFT;
                        int j = x1 >> FIXSHIFT;

                        if (i < len && j >= 0)
                        {
                            if (i == j)
                            {
                                // x0,x1 are the same pixel, so compute combined coverage
                                scanline[i] = (byte)(scanline[i] + (byte)(((x1 - x0) * max_weight) >> FIXSHIFT));
                            }
                            else
                            {
                                if (i >= 0)// add antialiasing for x0
                                {
                                    scanline[i] = (byte)(scanline[i] + (byte)(((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT));
                                }
                                else
                                {
                                    i = -1;  // clip
                                }
                                if (j < len) // add antialiasing for x1
                                {
                                    scanline[j] = (byte)(scanline[j] + (byte)(((x1 & FIXMASK) * max_weight) >> FIXSHIFT));
                                }
                                else
                                {
                                    j = len; // clip
                                }
                                i++;
                                while (i < j) // fill pixels between x0 and x1
                                {
                                    scanline[i] = (byte)(scanline[i] + (byte)max_weight);
                                    i++;
                                }
                            }
                        }
                    }
                }
                e = e.next;
            }
        }
Exemple #3
0
        private void RasterizeSortedEdges(GlyphBitmap bitmap, List <Edge> e, int vSubSamples, int offX, int off_y)
        {
            int eIndex = 0;

            ActiveEdge active     = null;
            int        max_weight = 255 / vSubSamples; // weight per vertical scanline

            int y = off_y * vSubSamples;

            int n        = e.Count - 1;
            var tempEdge = e[n];

            tempEdge.y0 = (off_y + bitmap.Height) * vSubSamples + 1;
            e[n]        = tempEdge;

            var scanline = new byte[bitmap.Width];

            float scanY = 0;

            int j = 0;

            while (j < bitmap.Height)
            {
                for (int iii = 0; iii < bitmap.Width; iii++)
                {
                    scanline[iii] = 0;
                }

                for (int s = 0; s < vSubSamples; s++)
                {
                    // find center of pixel for this scanline
                    scanY = y + 0.5f;

                    // update all active edges;
                    // remove all active edges that terminate before the center of this scanline
                    var        curr = active;
                    ActiveEdge prev = null;
                    while (curr != null)
                    {
                        if (curr.ey <= scanY)
                        {
                            // delete from list
                            if (prev != null)
                            {
                                prev.next = curr.next;
                            }
                            else
                            {
                                active = curr.next;
                            }

                            curr = curr.next;
                        }

                        else
                        {
                            curr.x += curr.dx; // advance to position for current scanline

                            prev = curr;
                            curr = curr.next; // advance through list
                        }
                    }

                    // resort the list if needed
                    bool changed;
                    do
                    {
                        changed = false;

                        curr = active;
                        prev = null;
                        while (curr != null && curr.next != null)
                        {
                            var prox = curr.next;
                            if (curr.x > prox.x)
                            {
                                if (prev == null)
                                {
                                    active = prox;
                                }
                                else
                                {
                                    prev.next = prox;
                                }

                                curr.next = prox.next;
                                prox.next = curr;
                                Console.WriteLine("Sorted " + curr.ey + " with " + prox.ey);
                                changed = true;
                            }

                            prev = curr;
                            curr = curr.next; // advance through list
                        }
                    } while (changed);

                    // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
                    while (e[eIndex].y0 <= scanY)
                    {
                        if (e[eIndex].y1 > scanY)
                        {
                            var z = CreateActiveEdge(e[eIndex], offX, scanY);
                            // find insertion point
                            if (active == null)
                            {
                                active = z;
                            }
                            else
                            if (z.x < active.x)  // insert at front
                            {
                                z.next = active;
                                active = z;
                            }
                            else
                            {
                                // find thing to insert AFTER
                                var p = active;
                                while (p.next != null && p.next.x < z.x)
                                {
                                    p = p.next;
                                }

                                // at this point, p->next->x is NOT < z->x
                                z.next = p.next;
                                p.next = z;
                            }
                        }

                        eIndex++;
                    }

                    // now process all active edges in XOR fashion
                    if (active != null)
                    {
                        FillActiveEdges(scanline, bitmap.Width, active, max_weight);
                    }

                    y++;
                }

                for (int iii = 0; iii < bitmap.Width; iii++)
                {
                    if (scanline[iii] > 0) // OPTIMIZATION?
                    {
                        int ofs = iii + j * bitmap.Width;
                        bitmap.Pixels[ofs] = scanline[iii];
                    }
                }

                j++;
            }
        }