source: svn/newcon3bcm2_21bu/dst/dmw/src/grp/jungle_font/_utfBitmapSubpixel.cxx

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 29.4 KB
Line 
1#include <stdio.h>
2#include <string.h>
3#include <malloc.h>
4#include "utfStruct.h"
5#include "utfRaster.h"
6
7//#define _SUBPIXEL_DEBUG_ON
8#ifdef _SUBPIXEL_DEBUG_ON
9        #include <stdio.h>
10        static FILE* dbg_fp;
11        static char space[] = "                                                  ";
12        static char* tab = space + sizeof(space);
13        #define _TI() tab -= 2
14        #define _TD() tab += 2
15        #define _SF(arg) fprintf(dbg_fp, tab); fprintf(dbg_fp, "### Start: "); fprintf arg; fprintf(dbg_fp, " ###\n"); _TI()
16        #define _EF(arg) _TD(); fprintf(dbg_fp, tab); fprintf(dbg_fp, "--- End: "); fprintf arg; fprintf(dbg_fp, " ---\n")
17        #define _OO(arg) fprintf(dbg_fp, tab); fprintf arg; fprintf(dbg_fp, "\n")
18        void OpenFreeTypeDebugFile() {dbg_fp = fopen("\\o.txt", "wt");}
19        void CloseFreeTypeDebugFile() {fclose(dbg_fp);}
20#else
21        #define _TI()
22        #define _TD()
23        #define _SF(arg)
24        #define _EF(arg)
25        #define _OO(arg)
26        void OpenFreeTypeDebugFile() {}
27        void CloseFreeTypeDebugFile() {}
28#endif
29
30#define PIXEL_BITS  8
31#define ONE_PIXEL   (1L << PIXEL_BITS)
32#define TRUNC(x)  ((TCoord)((x) >> PIXEL_BITS))
33#define SUBPIXELS(x)((TPos)(x) << PIXEL_BITS)
34#define UPSCALE(x)((x) <<(PIXEL_BITS - 6))
35#define DOWNSCALE(x)((x) >>(PIXEL_BITS - 6))
36#define FT_MAX_GRAY_SPANS  32
37
38#define FT_CURVE_TAG(flag)  (flag & 3)
39#define FT_CURVE_TAG_ON           1
40#define FT_CURVE_TAG_CONIC        0
41#define FT_CURVE_TAG_CUBIC        2
42
43typedef int   TCoord;   /* integer scanline/pixel coordinate */
44typedef long  TPos;     /* sub-pixel coordinate              */
45typedef int   TArea;
46typedef signed long  FT_Pos;
47typedef int          FT_Int;
48typedef unsigned int FT_UInt;
49
50typedef struct  FT_Vector
51{
52        FT_Pos  x;
53        FT_Pos  y;
54} FT_Vector;
55
56typedef struct FT_Outline
57{
58        int        nPath;
59        int        nPoint;
60        FT_Vector  points[4096];
61        UT_U8*     on;
62        UT_I16*    endPointIndex;
63} FT_Outline;
64
65typedef struct FT_Bitmap
66{
67        int             rows;
68        int             width;
69        int             pitch;
70        unsigned char*  buffer_;
71} FT_Bitmap;
72
73typedef struct FT_BBox
74{
75        FT_Pos  xMin, yMin;
76        FT_Pos  xMax, yMax;
77} FT_BBox;
78
79typedef struct FT_Span
80{
81        short           x;
82        unsigned short  len;
83        unsigned char   coverage;
84} FT_Span;
85
86typedef struct FT_Cell
87{
88        TCoord  x;
89        TCoord  y;
90        int     cover;
91        TArea   area;
92} FT_Cell;
93
94typedef struct FT_Raster
95{
96        FT_Cell*    cells;
97        int         max_cells;
98        int         num_cells;
99        TPos        min_ex, max_ex;
100        TPos        min_ey, max_ey;
101        TArea       area;
102        int         cover;
103        int         invalid;
104        TCoord      ex, ey;
105        TCoord      cx, cy;
106        TPos        x,  y;
107        TPos        last_ey;
108        FT_Vector   bez_stack[32 * 3 + 1];
109        int         lev_stack[32];
110        FT_Outline  outline;
111        FT_Bitmap   bitmap;
112        FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
113        int         num_gray_spans;
114        int         span_y;
115        int         conic_level;
116        int         cubic_level;
117} FT_Raster;
118
119/*
120void DispBitmap(FT_Bitmap* bitmap)
121{
122        FILE* fp = dbg_fp; //fopen("\\o.txt", "wt");
123        unsigned char* p = bitmap->buffer_;
124        int y;
125        for (y=0; y<bitmap->rows; y++)
126        {
127                int i, x = 0;
128                for (i=0; i<bitmap->width; i+=3,x++)
129                {
130                        int r = p[i+0];
131                        int g = p[i+1];
132                        int b = p[i+2];
133                        fprintf(fp, "%02x%02x%02x", r, g, b);
134                }
135                p += bitmap->pitch;
136                fprintf(fp, "\n");
137        }
138        fprintf(fp, "\n");
139        //fclose(fp);
140}
141*/
142
143static void gray_init_cells(FT_Raster* raster, void* buffer, long byte_size)
144{
145        raster->cells     = (FT_Cell*)buffer;
146        raster->max_cells = byte_size / sizeof(FT_Cell);
147        raster->num_cells = 0;
148        raster->area      = 0;
149        raster->cover     = 0;
150        raster->invalid   = 1;
151}
152
153static void gray_compute_cbox(FT_Raster* raster)
154{
155        int i = 0;
156        FT_Outline*  outline = &raster->outline;
157        FT_Vector*   vec     = outline->points;
158        FT_Vector*   limit   = vec + outline->nPoint;
159        _SF((dbg_fp, "gray_compute_cbox()"));
160        if (outline->nPoint <= 0)
161        {
162                raster->min_ex = raster->max_ex = 0;
163                raster->min_ey = raster->max_ey = 0;
164                _EF((dbg_fp, "gray_compute_cbox()"));
165                return;
166        }
167        raster->min_ex = raster->max_ex = vec->x;
168        raster->min_ey = raster->max_ey = vec->y;
169        _OO((dbg_fp, "point[%d] = %4d, %4d", i, vec->x, vec->y)); i++;
170        vec++;
171        for (; vec < limit; vec++)
172        {
173                TPos  x = vec->x;
174                TPos  y = vec->y;
175                if (x < raster->min_ex) raster->min_ex = x;
176                if (x > raster->max_ex) raster->max_ex = x;
177                if (y < raster->min_ey) raster->min_ey = y;
178                if (y > raster->max_ey) raster->max_ey = y;
179                _OO((dbg_fp, "point[%d] = %4d, %4d", i, vec->x, vec->y)); i++;
180        }
181        raster->min_ex = raster->min_ex >> 6;
182        raster->min_ey = raster->min_ey >> 6;
183        raster->max_ex = (raster->max_ex + 63) >> 6;
184        raster->max_ey = (raster->max_ey + 63) >> 6;
185        _OO((dbg_fp, "min_ex=%d, min_ey=%d, max_ex=%d, max_ey=%d", raster->min_ex, raster->min_ey, raster->max_ex, raster->max_ey));
186        _EF((dbg_fp, "gray_compute_cbox()"));
187}
188
189static void gray_record_cell(FT_Raster* raster)
190{
191        FT_Cell*  cell;
192        _SF((dbg_fp, "gray_record_cell()"));
193        if (!raster->invalid && (raster->area | raster->cover))
194        {
195                cell        = raster->cells + raster->num_cells++;
196                cell->x     = (TCoord)(raster->ex - raster->min_ex);
197                cell->y     = (TCoord)(raster->ey - raster->min_ey);
198                cell->area  = raster->area;
199                cell->cover = raster->cover;
200                _OO((dbg_fp, "cell[%d] x=%d, y=%d, area=%d, cover=%d", raster->num_cells-1, cell->x, cell->y, cell->area, cell->cover));
201        }
202        _EF((dbg_fp, "gray_record_cell()"));
203}
204
205static void gray_set_cell(FT_Raster* raster, TCoord ex, TCoord ey)
206{
207        int record = 0, clean = 1;
208        int invalid = (ey < raster->min_ey || ey >= raster->max_ey || ex >= raster->max_ex);
209        _SF((dbg_fp, "gray_set_cell(ex=%d, ey=%d)", ex, ey));
210        if (!invalid)
211        {
212                if (ex < raster->min_ex)
213                        ex = (TCoord)(raster->min_ex - 1);
214                if (ex != raster->ex || ey != raster->ey)
215                        record = 1;
216                else
217                        clean = raster->invalid;  /* do not clean if we didn't move from */
218        }
219        if (raster->invalid != invalid || record)
220                gray_record_cell(raster);
221        if (clean)
222        {
223                raster->area  = 0;
224                raster->cover = 0;
225        }
226        raster->invalid = invalid;
227        raster->ex      = ex;
228        raster->ey      = ey;
229        _OO((dbg_fp, "raster: ex=%d, ey=%d", raster->ex, raster->ey));
230        _EF((dbg_fp, "gray_set_cell()"));
231}
232
233static void gray_start_cell(FT_Raster* raster, TCoord ex, TCoord ey)
234{
235        _SF((dbg_fp, "gray_start_cell(ex=%d, ey=%d)", ex, ey));
236        if (ex < raster->min_ex) ex = (TCoord)(raster->min_ex - 1);
237        raster->area    = 0;
238        raster->cover   = 0;
239        raster->ex      = ex;
240        raster->ey      = ey;
241        raster->last_ey = SUBPIXELS(ey);
242        raster->invalid = 0;
243        _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover));
244        _OO((dbg_fp, "raster: ex=%d, ey=%d, last_ey=%d", raster->ex, raster->ey, raster->last_ey));
245        gray_set_cell(raster, ex, ey);
246        _EF((dbg_fp, "gray_start_cell()"));
247}
248
249static void gray_render_scanline(FT_Raster* raster, TCoord ey, TPos x1, TCoord y1, TPos x2, TCoord y2)
250{
251        TCoord  ex1, ex2, fx1, fx2, delta;
252        long    p, first, dx;
253        int     incr, lift, mod, rem;
254        _SF((dbg_fp, "gray_render_scanline(ey=%d, x1=%d, y1=%d, x2=%d, y2=%d)", ey, x1, y1, x2, y2));
255        dx = x2 - x1;
256        ex1 = TRUNC(x1); /* if (ex1 >= raster->max_ex) ex1 = raster->max_ex-1; */
257        ex2 = TRUNC(x2); /* if (ex2 >= raster->max_ex) ex2 = raster->max_ex-1; */
258        fx1 = (TCoord)(x1 - SUBPIXELS(ex1));
259        fx2 = (TCoord)(x2 - SUBPIXELS(ex2));
260        _OO((dbg_fp, "dx=%d, ex1=%d, ex2=%d, fx1=%d, fx2=%d", dx, ex1, ex2, fx1, fx2));
261        if (y1 == y2)
262        {
263                _OO((dbg_fp, "if (y1 == y2)"));
264                _TI();
265                gray_set_cell(raster, ex2, ey);
266                _TD();
267                _EF((dbg_fp, "gray_render_scanline(y1 == y2)"));
268                return;
269        }
270        if (ex1 == ex2)
271        {
272                _OO((dbg_fp, "if (ex1 == ex2)"));
273                _TI();
274                delta          = y2 - y1;
275                raster->area  += (TArea)(fx1 + fx2) * delta;
276                raster->cover += delta;
277                _OO((dbg_fp, "gray_set_cell(area=%d, cover=%d)", raster->area, raster->cover));
278                _TD();
279                _EF((dbg_fp, "gray_render_scanline(ex1 == ex2)"));
280                return;
281        }
282        p     = (ONE_PIXEL - fx1) * (y2 - y1);
283        first = ONE_PIXEL;
284        incr  = 1;
285        if (dx < 0)
286        {
287                p     = fx1 * (y2 - y1);
288                first = 0;
289                incr  = -1;
290                dx    = -dx;
291        }
292        delta = (TCoord)(p / dx);
293        mod   = (TCoord)(p % dx);
294        if (mod < 0)
295        {
296                delta--;
297                mod += (TCoord)dx;
298        }
299        _OO((dbg_fp, "p=%d, first=%d, incr=%d, delta=%d, mod=%d", p, first, incr, delta, mod));
300        raster->area  += (TArea)(fx1 + first) * delta;
301        raster->cover += delta;
302        _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover));
303        ex1 += incr;
304        gray_set_cell(raster, ex1, ey);
305        y1  += delta;
306        if (ex1 != ex2)
307        {
308                _OO((dbg_fp, "if (ex1 != ex2)"));
309                _TI();
310                p     = ONE_PIXEL * (y2 - y1 + delta);
311                lift  = (TCoord)(p / dx);
312                rem   = (TCoord)(p % dx);
313                if (rem < 0)
314                {
315                        lift--;
316                        rem += (TCoord)dx;
317                }
318                mod -= dx;
319                _OO((dbg_fp, "ex1=%d, ex2=%d, mod=%d", ex1, ex2));
320                _OO((dbg_fp, "p=%d, lift=%d, rem=%d, mod=%d, delta=%d", p, lift, rem, mod, delta));
321                _TI();
322                while (ex1 != ex2)
323                {
324                        delta = lift;
325                        mod  += rem;
326                        if (mod >= 0)
327                        {
328                                mod -= (TCoord)dx;
329                                delta++;
330                        }
331                        _OO((dbg_fp, "ex1=%d, ex2=%d, mod=%d", ex1, ex2));
332                        _OO((dbg_fp, "p=%d, lift=%d, rem=%d, mod=%d, delta=%d", p, lift, rem, mod, delta));
333                        raster->area  += (TArea)ONE_PIXEL * delta;
334                        raster->cover += delta;
335                        _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover));
336                        y1        += delta;
337                        ex1       += incr;
338                        gray_set_cell(raster, ex1, ey);
339                }
340                _TD();
341                _TD();
342        }
343        delta         = y2 - y1;
344        raster->area  += (TArea)(fx2 + ONE_PIXEL - first) * delta;
345        raster->cover += delta;
346        _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover));
347        _EF((dbg_fp, "gray_render_scanline()"));
348}
349
350static void gray_render_line(FT_Raster* raster, TPos to_x, TPos to_y)
351{
352        TCoord  ey1, ey2, fy1, fy2;
353        TPos    dx, dy, x, x2;
354        long    p, first;
355        int     delta, rem, mod, lift, incr;
356        _SF((dbg_fp, "gray_render_line(to_x=%d, to_y=%d)", to_x, to_y));
357        ey1 = TRUNC(raster->last_ey);
358        ey2 = TRUNC(to_y); /* if (ey2 >= raster->max_ey) ey2 = raster->max_ey-1; */
359        fy1 = (TCoord)(raster->y - raster->last_ey);
360        fy2 = (TCoord)(to_y - SUBPIXELS(ey2));
361        dx = to_x - raster->x;
362        dy = to_y - raster->y;
363        _OO((dbg_fp, "dx=%d, dy=%d", dx, dy));
364        _OO((dbg_fp, "ey1=%d, ey2=%d, fy1=%d, fy2=%d", ey1, ey2, fy1, fy2));
365        {
366                TCoord  min, max;
367                min = ey1;
368                max = ey2;
369                if (ey1 > ey2)
370                {
371                        min = ey2;
372                        max = ey1;
373                }
374                if (min >= raster->max_ey || max < raster->min_ey) goto End;
375        }
376        if (ey1 == ey2)
377        {
378                _OO((dbg_fp, "if (ey1 == ey2)"));
379                _TI();
380                gray_render_scanline(raster, ey1, raster->x, fy1, to_x, fy2);
381                _TD();
382                goto End;
383        }
384        incr = 1;
385        if (dx == 0)
386        {
387                TCoord  ex     = TRUNC(raster->x);
388                TCoord  two_fx = (TCoord)((raster->x - SUBPIXELS(ex)) << 1);
389                TPos    area;
390                _OO((dbg_fp, "if (dx == 0)"));
391                _TI();
392                first = ONE_PIXEL;
393                if (dy < 0)
394                {
395                        first = 0;
396                        incr  = -1;
397                }
398                delta          = (int)(first - fy1);
399                raster->area  += (TArea)two_fx * delta;
400                raster->cover += delta;
401                ey1           += incr;
402                _OO((dbg_fp, "raster: area=%d, cover=%d,,, ey1=%d", raster->area, raster->cover, ey1));
403                gray_set_cell(raster, ex, ey1);
404                delta = (int)(first + first - ONE_PIXEL);
405                area  = (TArea)two_fx * delta;
406                _TI();
407                while (ey1 != ey2)
408                {
409                        raster->area  += area;
410                        raster->cover += delta;
411                        ey1           += incr;
412                        _OO((dbg_fp, "raster: area=%d, cover=%d,,, ey1=%d", raster->area, raster->cover, ey1));
413                        gray_set_cell(raster, ex, ey1);
414                }
415                _TD();
416                delta          = (int)(fy2 - ONE_PIXEL + first);
417                raster->area  += (TArea)two_fx * delta;
418                raster->cover += delta;
419                _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover));
420                _TD();
421                goto End;
422        }
423        p     = (ONE_PIXEL - fy1) * dx;
424        first = ONE_PIXEL;
425        incr  = 1;
426        if (dy < 0)
427        {
428                p     = fy1 * dx;
429                first = 0;
430                incr  = -1;
431                dy    = -dy;
432        }
433        delta = (int)(p / dy);
434        mod   = (int)(p % dy);
435        if (mod < 0)
436        {
437                delta--;
438                mod += (TCoord)dy;
439        }
440        x = raster->x + delta;
441        _OO((dbg_fp, "p=%d, first=%d, incr=%d, delta=%d, mod=%d, dy=%d", p, first, incr, delta, mod, dy));
442        gray_render_scanline(raster, ey1, raster->x, fy1, x,(TCoord)first);
443        ey1 += incr;
444        gray_set_cell(raster, TRUNC(x), ey1);
445        if (ey1 != ey2)
446        {
447                _OO((dbg_fp, "if (ey1 != ey2)"));
448                _TI();
449                p     = ONE_PIXEL * dx;
450                lift  = (int)(p / dy);
451                rem   = (int)(p % dy);
452                if (rem < 0)
453                {
454                        lift--;
455                        rem += (int)dy;
456                }
457                mod -= (int)dy;
458                _OO((dbg_fp, "ey1=%d, ey2=%d, mod=%d", ey1, ey2));
459                _OO((dbg_fp, "p=%d, lift=%d, rem=%d, mod=%d, delta=%d", p, lift, rem, mod, delta));
460                _TI();
461                while (ey1 != ey2)
462                {
463                        delta = lift;
464                        mod  += rem;
465                        if (mod >= 0)
466                        {
467                                mod -= (int)dy;
468                                delta++;
469                        }
470                        x2 = x + delta;
471                        _OO((dbg_fp, "ey1=%d, ey2=%d, mod=%d", ey1, ey2));
472                        _OO((dbg_fp, "p=%d, lift=%d, rem=%d, mod=%d, delta=%d", p, lift, rem, mod, delta));
473                        gray_render_scanline(raster, ey1, x, (TCoord)(ONE_PIXEL - first), x2, (TCoord)first);
474                        x = x2;
475                        ey1 += incr;
476                        gray_set_cell(raster, TRUNC(x), ey1);
477                }
478                _TD();
479                _TD();
480        }
481        gray_render_scanline(raster, ey1, x, (TCoord)(ONE_PIXEL - first), to_x, fy2);
482        End:
483        raster->x       = to_x;
484        raster->y       = to_y;
485        raster->last_ey = SUBPIXELS(ey2);
486        _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover));
487        _EF((dbg_fp, "gray_render_line()"));
488}
489
490static void gray_split_conic(FT_Vector*  base)
491{
492        TPos  a, b;
493        base[4].x = base[2].x;
494        b = base[1].x;
495        a = base[3].x = (base[2].x + b) / 2;
496        b = base[1].x = (base[0].x + b) / 2;
497        base[2].x = (a + b) / 2;
498        base[4].y = base[2].y;
499        b = base[1].y;
500        a = base[3].y = (base[2].y + b) / 2;
501        b = base[1].y = (base[0].y + b) / 2;
502        base[2].y = (a + b) / 2;
503}
504
505static void gray_render_conic(FT_Raster* raster, FT_Vector* control, FT_Vector* to)
506{
507        TPos        dx, dy;
508        int         top, level;
509        int*        levels;
510        FT_Vector*  arc;
511        dx = DOWNSCALE(raster->x) + to->x -(control->x << 1);
512        if (dx < 0)
513        dx = -dx;
514        dy = DOWNSCALE(raster->y) + to->y -(control->y << 1);
515        if (dy < 0)
516        dy = -dy;
517        if (dx < dy)
518        dx = dy;
519
520        level = 1;
521        dx = dx / raster->conic_level;
522        while (dx > 0)
523        {
524        dx >>= 2;
525        level++;
526        }
527
528        /* a shortcut to speed things up */
529        if (level <= 1)
530        {
531        /* we compute the mid-point directly in order to avoid */
532        /* calling gray_split_conic()                          */
533        TPos   to_x, to_y, mid_x, mid_y;
534
535
536        to_x  = UPSCALE(to->x);
537        to_y  = UPSCALE(to->y);
538        mid_x = (raster->x + to_x + 2 * UPSCALE(control->x)) / 4;
539        mid_y = (raster->y + to_y + 2 * UPSCALE(control->y)) / 4;
540
541        gray_render_line(raster, mid_x, mid_y);
542        gray_render_line(raster, to_x, to_y);
543        return;
544        }
545
546        arc       = raster->bez_stack;
547        levels    = raster->lev_stack;
548        top       = 0;
549        levels[0] = level;
550
551        arc[0].x = UPSCALE(to->x);
552        arc[0].y = UPSCALE(to->y);
553        arc[1].x = UPSCALE(control->x);
554        arc[1].y = UPSCALE(control->y);
555        arc[2].x = raster->x;
556        arc[2].y = raster->y;
557
558        while (top >= 0)
559        {
560        level = levels[top];
561        if (level > 1)
562        {
563        /* check that the arc crosses the current band */
564        TPos  min, max, y;
565
566
567        min = max = arc[0].y;
568
569        y = arc[1].y;
570        if (y < min) min = y;
571        if (y > max) max = y;
572
573        y = arc[2].y;
574        if (y < min) min = y;
575        if (y > max) max = y;
576
577        if (TRUNC(min) >= raster->max_ey || TRUNC(max) < raster->min_ey)
578        goto Draw;
579
580        gray_split_conic(arc);
581        arc += 2;
582        top++;
583        levels[top] = levels[top - 1] = level - 1;
584        continue;
585        }
586
587        Draw:
588        {
589        TPos  to_x, to_y, mid_x, mid_y;
590
591
592        to_x  = arc[0].x;
593        to_y  = arc[0].y;
594        mid_x = (raster->x + to_x + 2 * arc[1].x) / 4;
595        mid_y = (raster->y + to_y + 2 * arc[1].y) / 4;
596
597        gray_render_line(raster, mid_x, mid_y);
598        gray_render_line(raster, to_x, to_y);
599
600        top--;
601        arc -= 2;
602        }
603        }
604        return;
605}
606
607static void gray_split_cubic(FT_Vector*  base)
608{
609        TPos  a, b, c, d;
610        base[6].x = base[3].x;
611        c = base[1].x;
612        d = base[2].x;
613        base[1].x = a = (base[0].x + c) / 2;
614        base[5].x = b = (base[3].x + d) / 2;
615        c = (c + d) / 2;
616        base[2].x = a = (a + c) / 2;
617        base[4].x = b = (b + c) / 2;
618        base[3].x = (a + b) / 2;
619        base[6].y = base[3].y;
620        c = base[1].y;
621        d = base[2].y;
622        base[1].y = a = (base[0].y + c) / 2;
623        base[5].y = b = (base[3].y + d) / 2;
624        c = (c + d) / 2;
625        base[2].y = a = (a + c) / 2;
626        base[4].y = b = (b + c) / 2;
627        base[3].y = (a + b) / 2;
628}
629
630static void gray_render_cubic(FT_Raster* raster, FT_Vector* control1, FT_Vector* control2, FT_Vector* to)
631{
632        TPos        dx, dy, da, db;
633        int         top, level;
634        int*        levels;
635        FT_Vector*  arc;
636
637        dx = DOWNSCALE(raster->x) + to->x -(control1->x << 1);
638        if (dx < 0)
639        dx = -dx;
640        dy = DOWNSCALE(raster->y) + to->y -(control1->y << 1);
641        if (dy < 0)
642        dy = -dy;
643        if (dx < dy)
644        dx = dy;
645        da = dx;
646
647        dx = DOWNSCALE(raster->x) + to->x - 3 * (control1->x + control2->x);
648        if (dx < 0)
649        dx = -dx;
650        dy = DOWNSCALE(raster->y) + to->y - 3 * (control1->x + control2->y);
651        if (dy < 0)
652        dy = -dy;
653        if (dx < dy)
654        dx = dy;
655        db = dx;
656
657        level = 1;
658        da    = da / raster->cubic_level;
659        db    = db / raster->conic_level;
660        while (da > 0 || db > 0)
661        {
662        da >>= 2;
663        db >>= 3;
664        level++;
665        }
666
667        if (level <= 1)
668        {
669        TPos   to_x, to_y, mid_x, mid_y;
670
671
672        to_x  = UPSCALE(to->x);
673        to_y  = UPSCALE(to->y);
674        mid_x = (raster->x + to_x +
675        3 * UPSCALE(control1->x + control2->x)) / 8;
676        mid_y = (raster->y + to_y +
677        3 * UPSCALE(control1->y + control2->y)) / 8;
678
679        gray_render_line(raster, mid_x, mid_y);
680        gray_render_line(raster, to_x, to_y);
681        return;
682        }
683
684        arc      = raster->bez_stack;
685        arc[0].x = UPSCALE(to->x);
686        arc[0].y = UPSCALE(to->y);
687        arc[1].x = UPSCALE(control2->x);
688        arc[1].y = UPSCALE(control2->y);
689        arc[2].x = UPSCALE(control1->x);
690        arc[2].y = UPSCALE(control1->y);
691        arc[3].x = raster->x;
692        arc[3].y = raster->y;
693
694        levels    = raster->lev_stack;
695        top       = 0;
696        levels[0] = level;
697
698        while (top >= 0)
699        {
700        level = levels[top];
701        if (level > 1)
702        {
703        /* check that the arc crosses the current band */
704        TPos  min, max, y;
705
706
707        min = max = arc[0].y;
708        y = arc[1].y;
709        if (y < min) min = y;
710        if (y > max) max = y;
711        y = arc[2].y;
712        if (y < min) min = y;
713        if (y > max) max = y;
714        y = arc[3].y;
715        if (y < min) min = y;
716        if (y > max) max = y;
717        if (TRUNC(min) >= raster->max_ey || TRUNC(max) < 0)
718        goto Draw;
719        gray_split_cubic(arc);
720        arc += 3;
721        top ++;
722        levels[top] = levels[top - 1] = level - 1;
723        continue;
724        }
725
726        Draw:
727        {
728        TPos  to_x, to_y, mid_x, mid_y;
729
730
731        to_x  = arc[0].x;
732        to_y  = arc[0].y;
733        mid_x = (raster->x + to_x + 3 * (arc[1].x + arc[2].x)) / 8;
734        mid_y = (raster->y + to_y + 3 * (arc[1].y + arc[2].y)) / 8;
735
736        gray_render_line(raster, mid_x, mid_y);
737        gray_render_line(raster, to_x, to_y);
738        top --;
739        arc -= 3;
740        }
741        }
742        return;
743}
744
745#define PACK(a)      (((long)(a)->y << 16) +(a)->x)
746#define LESS_THAN(a, b)(PACK(a) < PACK(b))
747#define SWAP_CELLS(a, b, temp)  do { temp = * (a); * (a) = * (b); * (b) = temp; } while (0)
748#define QSORT_THRESHOLD  9
749
750static void gray_quick_sort(FT_Cell* cells, int count)
751{
752        FT_Cell*  stack[40];  /* should be enough ;-) */
753        FT_Cell** top;        /* top of stack */
754        FT_Cell*  base;
755        FT_Cell*  limit;
756        FT_Cell   temp;
757
758        limit = cells + count;
759        base  = cells;
760        top   = stack;
761
762        for (;;)
763        {
764        int    len = (int)(limit - base);
765        FT_Cell* i;
766        FT_Cell* j;
767        FT_Cell* pivot;
768
769
770        if (len > QSORT_THRESHOLD)
771        {
772        /* we use base + len/2 as the pivot */
773        pivot = base + len / 2;
774        SWAP_CELLS(base, pivot, temp);
775
776        i = base + 1;
777        j = limit - 1;
778
779        /* now ensure that *i <= *base <= *j */
780        if (LESS_THAN(j, i))
781        SWAP_CELLS(i, j, temp);
782
783        if (LESS_THAN(base, i))
784        SWAP_CELLS(base, i, temp);
785
786        if (LESS_THAN(j, base))
787        SWAP_CELLS(base, j, temp);
788
789        for (;;)
790        {
791        do i++; while (LESS_THAN(i, base));
792        do j--; while (LESS_THAN(base, j));
793
794        if (i > j)
795        break;
796
797        SWAP_CELLS(i, j, temp);
798        }
799
800        SWAP_CELLS(base, j, temp);
801
802        /* now, push the largest sub-array */
803        if (j - base > limit - i)
804        {
805        top[0] = base;
806        top[1] = j;
807        base   = i;
808        }
809        else
810        {
811        top[0] = i;
812        top[1] = limit;
813        limit  = j;
814        }
815        top += 2;
816        }
817        else
818        {
819        /* the sub-array is small, perform insertion sort */
820        j = base;
821        i = j + 1;
822
823        for (; i < limit; j = i, i++)
824        {
825        for (; LESS_THAN(j + 1, j); j--)
826        {
827        SWAP_CELLS(j + 1, j, temp);
828        if (j == base)
829        break;
830        }
831        }
832        if (top > stack)
833        {
834        top  -= 2;
835        base  = top[0];
836        limit = top[1];
837        }
838        else
839        break;
840        }
841        }
842}
843
844static void  FT_Outline_Translate(FT_Outline* outline, FT_Pos xOffset, FT_Pos yOffset)
845{
846        int   n;
847        FT_Vector*  vec = outline->points;
848        for (n = 0; n < outline->nPoint; n++)
849        {
850                vec->x += xOffset;
851                vec->y += yOffset;
852                vec++;
853        }
854}
855
856static void gray_render_span(int y, int count, FT_Span* spans, FT_Raster* raster)
857{
858        unsigned char*  p;
859        FT_Bitmap*      map = &raster->bitmap;
860        _SF((dbg_fp, "gray_render_span(y=%d, count=%d)", y, count));
861        p = (unsigned char*)map->buffer_ - y * map->pitch;
862        if (map->pitch >= 0) p += (map->rows - 1) * map->pitch;
863        for (; count > 0; count--, spans++)
864        {
865                if (spans->coverage)
866                {
867                        _OO((dbg_fp, "spans->x=%d, spans->len=%d, spans->coverage=%d", spans->x, spans->len, spans->coverage));
868                        memset(p+spans->x, spans->coverage, spans->len);
869                }
870        }
871        _EF((dbg_fp, "gray_render_span()"));
872}
873
874static void gray_hline(FT_Raster* raster, TCoord x, TCoord y, TPos area, int acount)
875{
876        FT_Span*   span;
877        int        count;
878        int        coverage;
879        _SF((dbg_fp, "gray_hline(x=%d, y=%d, area=%d, acount=%d)", x, y, area, acount));
880        coverage = (int)(area >>(PIXEL_BITS * 2 + 1 - 8));
881        _OO((dbg_fp, "coverage=%d", coverage));
882        if (coverage < 0) coverage = -coverage;
883        if (coverage >= 256) coverage = 255;
884        y += (TCoord)raster->min_ey;
885        x += (TCoord)raster->min_ex;
886        _OO((dbg_fp, "coverage=%d, x=%d, y=%d", coverage, x, y));
887        if (coverage)
888        {
889                _OO((dbg_fp, "if (coverage)"));
890                _TI();
891                count = raster->num_gray_spans;
892                span  = raster->gray_spans + count - 1;
893                _OO((dbg_fp, "raster->num_gray_spans=%d, span[%d]", count, span-raster->gray_spans));
894                if (count > 0 && raster->span_y == y && (int)span->x + span->len == (int)x && span->coverage == coverage)
895                {
896                        _OO((dbg_fp, "if (count > 0 && raster->span_y == y && (int)span->x + span->len == (int)x && span->coverage == coverage)"));
897                        _TI();
898                        span->len = (unsigned short)(span->len + acount);
899                        _OO((dbg_fp, "span->len=%d", span->len));
900                        _TD();
901                        _EF((dbg_fp, "gray_hline()"));
902                        return;
903                }
904                if (raster->span_y != y || count >= FT_MAX_GRAY_SPANS)
905                {
906                        _OO((dbg_fp, "if (raster->span_y != y || count >= FT_MAX_GRAY_SPANS)"));
907                        _TI();
908                        if (count > 0) gray_render_span(raster->span_y, count, raster->gray_spans, raster);
909                        raster->num_gray_spans = 0;
910                        raster->span_y         = y;
911                        count = 0;
912                        span  = raster->gray_spans;
913                        _OO((dbg_fp, "raster: num_gray_spans=%d, span_y=%d", raster->num_gray_spans, raster->span_y));
914                        _OO((dbg_fp, "count=0, span[%d]", span-raster->gray_spans));
915                        _TD();
916                }
917                else span++;
918                span->x        = (short)x;
919                span->len      = (unsigned short)acount;
920                span->coverage = (unsigned char)coverage;
921                raster->num_gray_spans++;
922                _OO((dbg_fp, "span[%d]: x=%d, len=%d, coverage=%d", span-raster->gray_spans, span->x, span->len, span->coverage));
923                _TD();
924        }
925        _EF((dbg_fp, "gray_hline()"));
926}
927
928static void gray_sweep(FT_Raster* raster, FT_Bitmap* bitmap)
929{
930        TCoord  x, y, cover;
931        TArea   area;
932        FT_Cell*  start;
933        FT_Cell*  limit;
934        FT_Cell*  cur;
935        if (raster->num_cells == 0) return;
936        _SF((dbg_fp, "gray_sweep()"));
937        cur   = raster->cells;
938        limit = cur + raster->num_cells;
939        cover                  = 0;
940        raster->span_y         = -1;
941        raster->num_gray_spans = 0;
942        _OO((dbg_fp, "limit=%d, cover=%d", limit, cover));
943        _OO((dbg_fp, "raster: limit=%d, num_gray_spans=%d", raster->span_y, raster->num_gray_spans));
944        _TI();
945        for (;;)
946        {
947                start  = cur;
948                y      = start->y;
949                x      = start->x;
950                area   = start->area;
951                cover += start->cover;
952                _OO((dbg_fp, "start=%d, x=%d, y=%d, area=%d, cover=%d", start-raster->cells, x, y, area, cover));
953                _TI();
954                for (;;)
955                {
956                        ++cur;
957                        if (cur >= limit || cur->y != start->y || cur->x != start->x) break;
958                        area  += cur->area;
959                        cover += cur->cover;
960                        _OO((dbg_fp, "cur=%d, area=%d, cover=%d", cur-raster->cells, area, cover));
961                }
962                if (area && x >= 0)
963                {
964                        _OO((dbg_fp, "if (area && x >= 0)"));
965                        _TI();
966                        gray_hline(raster, x, y, cover * (ONE_PIXEL * 2) - area, 1);
967                        x++;
968                        _TD();
969                }
970                if (x < 0) x = 0;
971                if (cur < limit && start->y == cur->y)
972                {
973                        _OO((dbg_fp, "if (cur < limit && start->y == cur->y)"));
974                        _TI();
975                        if (cur->x > x) gray_hline(raster, x, y, cover * (ONE_PIXEL * 2), cur->x - x);
976                        _TD();
977                }
978                else
979                {
980                        _OO((dbg_fp, "else"));
981                        _TI();
982                        if (cover && x < raster->max_ex - raster->min_ex) gray_hline(raster, x, y, cover * (ONE_PIXEL * 2), (int)(raster->max_ex - x - raster->min_ex));
983                        cover = 0;
984                        _TD();
985                }
986                _TD();
987                if (cur >= limit) break;
988        }
989        _TD();
990        if (raster->num_gray_spans > 0) gray_render_span(raster->span_y, raster->num_gray_spans, raster->gray_spans, raster);
991        _EF((dbg_fp, "gray_sweep()"));
992}
993
994static void gray_move_to(FT_Vector* to, FT_Raster* raster)
995{
996        TPos x, y;
997        _SF((dbg_fp, "gray_move_to()"));
998        gray_record_cell(raster);
999        x = UPSCALE(to->x);
1000        y = UPSCALE(to->y);
1001        gray_start_cell(raster, TRUNC(x), TRUNC(y));
1002        raster->x = x;
1003        raster->y = y;
1004        _EF((dbg_fp, "gray_move_to()"));
1005}
1006
1007static int gray_raster_render(FT_Raster* raster)
1008{
1009        FT_Outline* outline = &raster->outline;
1010        FT_Bitmap*  bitmap  = &raster->bitmap;
1011        FT_Vector   v_last;
1012        FT_Vector   v_control;
1013        FT_Vector   v_start;
1014        FT_Vector*  point;
1015        FT_Vector*  limit;
1016        char*       on;
1017        FT_Int      n;         /* index of contour in outline     */
1018        FT_UInt     first = 0; /* index of first point in contour */
1019        FT_Int      tag;       /* current point's state           */
1020        _SF((dbg_fp, "gray_raster_render()"));
1021        gray_compute_cbox(raster);
1022        raster->num_cells   = 0;
1023        raster->invalid     = 1;
1024        raster->conic_level = 32;
1025        raster->cubic_level = 16;
1026        if (raster->max_ex > 24 || raster->max_ey > 24)
1027        {
1028                raster->conic_level <<= 1;
1029                raster->cubic_level <<= 1;
1030        }
1031        for (n = 0; n < outline->nPath; n++)
1032        {
1033                FT_Int  last;  /* index of last point in contour */
1034                last  = outline->endPointIndex[n];
1035                limit = outline->points + last;
1036                v_start = outline->points[first];
1037                v_last  = outline->points[last];
1038                v_control = v_start;
1039                point = outline->points + first;
1040                on  = outline->on  + first;
1041                tag   = FT_CURVE_TAG(on[0]);
1042                if (tag == FT_CURVE_TAG_CONIC)
1043                {
1044                        /* first point is conic control.  Yes, this happens. */
1045                        if (FT_CURVE_TAG(outline->on[last]) == FT_CURVE_TAG_ON)
1046                        {
1047                                /* start at last point if it is on the curve */
1048                                v_start = v_last;
1049                                limit--;
1050                        }
1051                        else
1052                        {
1053                                /* if both first and last points are conic,         */
1054                                /* start at their middle and record its position    */
1055                                /* for closure                                      */
1056                                v_start.x = (v_start.x + v_last.x) / 2;
1057                                v_start.y = (v_start.y + v_last.y) / 2;
1058                                v_last = v_start;
1059                        }
1060                        point--;
1061                        on--;
1062                }
1063                gray_move_to(&v_start, raster);
1064                while (point < limit)
1065                {
1066                        point++;
1067                        on++;
1068                        tag = FT_CURVE_TAG(on[0]);
1069                        switch (tag)
1070                        {
1071                                case FT_CURVE_TAG_ON:  /* emit a single line_to */
1072                                {
1073                                        gray_render_line(raster, UPSCALE(point->x), UPSCALE(point->y));
1074                                        continue;
1075                                }
1076                                case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
1077                                        v_control.x = point->x;
1078                                        v_control.y = point->y;
1079                                        Do_Conic:
1080                                        if (point < limit)
1081                                        {
1082                                                FT_Vector  vec;
1083                                                FT_Vector  v_middle;
1084                                                point++;
1085                                                on++;
1086                                                tag = FT_CURVE_TAG(on[0]);
1087                                                vec.x = point->x;
1088                                                vec.y = point->y;
1089                                                if (tag == FT_CURVE_TAG_ON)
1090                                                {
1091                                                        gray_render_conic(raster, &v_control, &vec);
1092                                                        continue;
1093                                                }
1094                                                v_middle.x = (v_control.x + vec.x) / 2;
1095                                                v_middle.y = (v_control.y + vec.y) / 2;
1096                                                gray_render_conic(raster, &v_control, &v_middle);
1097                                                v_control = vec;
1098                                                goto Do_Conic;
1099                                        }
1100                                        gray_render_conic(raster, &v_control, &v_start);
1101                                        goto Close;
1102                                default:  /* FT_CURVE_TAG_CUBIC */
1103                                {
1104                                        FT_Vector  vec1, vec2;
1105                                        point += 2;
1106                                        on  += 2;
1107                                        vec1.x = point[-2].x; vec1.y = point[-2].y;
1108                                        vec2.x = point[-1].x; vec2.y = point[-1].y;
1109                                        if (point <= limit)
1110                                        {
1111                                                FT_Vector  vec;
1112                                                vec.x = point->x;
1113                                                vec.y = point->y;
1114                                                gray_render_cubic(raster, &vec1, &vec2, &vec);
1115                                                continue;
1116                                        }
1117                                        gray_render_cubic(raster, &vec1, &vec2, &v_start);
1118                                        goto Close;
1119                                }
1120                        }
1121                }
1122                /* close the contour with a line segment */
1123                gray_render_line(raster, UPSCALE(v_start.x), UPSCALE(v_start.y));
1124                Close: first = last + 1;
1125        }
1126        gray_record_cell(raster);
1127        gray_quick_sort(raster->cells, raster->num_cells);
1128        gray_sweep(raster,  &raster->bitmap);
1129        _EF((dbg_fp, "gray_raster_render()"));
1130        return 0;
1131}
1132
1133static char pool_base[0x100000];
1134static FT_Raster raster;
1135
1136void ut_SubpixelScale(UT_FONT_TASK* task, UT_IMAGE* image)
1137{
1138        int i;
1139        gray_init_cells(&raster, pool_base, sizeof(pool_base));
1140
1141        ut_AllocScanBuffer(task, image, image->lSize);
1142        raster.bitmap.buffer_ = image->data;
1143        raster.bitmap.width   = image->bbox.sx;
1144        raster.bitmap.rows    = image->bbox.sy;
1145        raster.bitmap.pitch   = image->bSize;
1146        memset(image->data, 0, image->lSize);
1147
1148        raster.outline.nPath         = task->rootGlyph.nPath;
1149        raster.outline.nPoint        = task->rootGlyph.nPoint;
1150        raster.outline.on            = task->rootGlyph.on;
1151        raster.outline.endPointIndex = task->rootGlyph.endPointIndex;
1152        for (i=0; i<task->rootGlyph.nPoint; i++)
1153        {
1154                raster.outline.points[i].x = task->rootGlyph.x[i] / 8;
1155                raster.outline.points[i].y = task->rootGlyph.y[i] / 8;
1156                raster.outline.on[i] = 1;
1157        }
1158        gray_raster_render(&raster);
1159}
Note: See TracBrowser for help on using the repository browser.