source: svn/newcon3bcm2_21bu/dst/dmw/src/grp/jungle_font/OutLine.txt

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

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

  • Property svn:executable set to *
File size: 121.3 KB
Line 
1#include <string.h>
2#include "utStruct.h"
3#include "_utDebugOn.hxx"
4
5//#define _UT_USE_DROPOUT_COLTROL
6#define _UT_USE_OLD_SCAN_CONVERSION
7
8/***************************************************************************/
9
10#define _UT_ONE_PIXEL   64
11#define _UT_HALF_PIXEL  32
12
13char* ut_AllocScanBuffer(UT_FONT_TASK* task, UT_IMAGE* image, int size);
14UT_BOOL ut_PrepareRasterGlyphBitmap(UT_FC* fc, UT_IMAGE* image);
15void ut_BitmapEffect(UT_FC* fc, UT_IMAGE* image);
16void ut_Bit2ByteImage(UT_FONT_MANAGER* fontManager,
17                                          unsigned char* bit_image,  int bit_bSize,
18                                          unsigned char* byte_image, int byte_bSize,
19                                          int xSize, int ySize, int ox, int oy);
20void ut_Bit2ByteImageP(UT_FONT_MANAGER* fontManager,
21                                           unsigned char* bit_image,
22                                           unsigned char* byte_image, int byte_bSize,
23                                           int xSize, int ySize, int ox, int oy);
24
25#ifndef _UT_DEBUG
26        #ifdef _UT_DEBUG_SCAN
27                #undef _UT_DEBUG_SCAN
28        #endif
29#endif
30
31#ifdef _UT_DEBUG_SCAN
32        void ut_cbDebugScanCheckBuffer(UT_FONT_TASK* task, char* file, int line);
33        #define UT_DEBUG_SCAN_CHECK_BUFFER(task) ut_cbDebugScanCheckBuffer(task, __FILE__, __LINE__)
34#else
35        #define UT_DEBUG_SCAN_CHECK_BUFFER(task)
36#endif
37
38/***************************************************************************/
39
40#define ut_IsByteImage(fc)              0/*(fc->rasterType < _UT_RASTER_TYPE_GRAY_2)*/
41
42#define ut_GetPixel(task, x, y) (((y) < task->i_ySize) && ((y) >= 0)) ? task->image[(y)*task->i_bSize+((x)>>5)] & (0x80000000>>((x)&0x1f)) : 0
43#define ut_SetPixel(task, x, y) task->image[(y)*task->i_bSize+((x)>>5)] |= (0x80000000>>((x)&0x1f))
44void ut_SetPixel2(UT_FONT_TASK* task, int x, int y)
45{
46        int i;
47        UT_U32* p = task->image + y*task->i_bSize + (x >> 5);
48        UT_U32* m = task->strokeMask->bitmap;
49        int shift = x & 0x1f;
50        int remainder = shift + task->strokeMask->size - 32;
51        if (remainder > 0) remainder = task->strokeMask->size - remainder;
52        else remainder = 0;
53        if (x >= 27)
54        {
55                int rrr = x;
56        }
57        for (i=0; i<task->strokeMask->size; i++)
58        {
59                *p |= *m >> shift;
60                if (remainder) p[1] |= *m << remainder;
61                m++;
62                p += task->i_bSize;
63        }
64}
65
66#define ut_IsOnScanLine(o)                      (((o) & (_UT_ONE_PIXEL-1)) == _UT_HALF_PIXEL)
67#define ut_AboveScanLine(o)                     (((o+_UT_HALF_PIXEL)   & (-1<<6)) + _UT_HALF_PIXEL)
68#define ut_BelowScanLine(o)                     (((o-_UT_HALF_PIXEL-1) & (-1<<6)) + _UT_HALF_PIXEL)
69#define ut_AboveScanDelta(o)            (((95-((o)&63))&63)+1)
70#define ut_BelowScanDelta(o)            ((((o)+31)&63)+1)
71#define ut_AbovePixel(o)                        ((o+_UT_HALF_PIXEL)  >>_UT_PIXEL_SHIFT)
72#define ut_BelowPixel(o)                        ((o-_UT_HALF_PIXEL-1)>>_UT_PIXEL_SHIFT)
73#define ut_ExceptionAbovePixel(o)       ((o+_UT_HALF_PIXEL-1)>>_UT_PIXEL_SHIFT)
74
75UT_STATIC_API void ut_CheckLastPoint(UT_FONT_TASK* task, UT_COORD o_x2, UT_COORD o_y2);
76UT_STATIC_API void ut_FillLineMono(int start, int stop, UT_U32* image);
77UT_STATIC_API void ut_FillLineGray(int start, int stop, int shift, int level, unsigned char* image);
78
79/***************************************************************************/
80
81#ifdef _UT_USE_CACHE
82
83#define _UT_HASH_DEPTH 111
84#define ut_GetFcIdentifier0(fc) ((fc->xSize<<16) | (fc->ySize))
85#define ut_GetFcIdentifier1(fc) ((fc->edgeType<<24) | (fc->rasterType<<16) | (fc->isItalic<<1) | (fc->isBold))
86#define ut_GetFcIdentifier2(fc,code) ((fc->isFixedPitch<<16) | (code))
87#define ut_GetHashIndex(identifier0, identifier1, identifier2) ((identifier0 + identifier1 + identifier2) % _UT_HASH_DEPTH)
88
89typedef struct UT_CAHCE_NODE
90{
91        UT_U32                fontID;
92        UT_U32                identifier0; /* (xSize<<16) | (ySize)*/
93        UT_U32                identifier1; /* (edgeType<<16) | (isItalic<<1) | (isBold)*/
94        UT_U32                identifier2; /* (isFixedPitch<<16) | (code)*/
95        signed short          width;
96        signed short          height;
97        signed short          bSize;
98        signed short          lSize;
99        signed short          type;
100        UT_BBOX               bbox;
101        struct UT_CAHCE_NODE* gPrev;
102        struct UT_CAHCE_NODE* gNext;
103        struct UT_CAHCE_NODE* lPrev;
104        struct UT_CAHCE_NODE* lNext;
105} UT_CAHCE_NODE;
106
107typedef struct UT_CACHE
108{
109        char* staticBuffer;
110        unsigned memorySize;
111        unsigned usedMemorySize;
112        int lowestSize;
113        int highestSize;
114        UT_CAHCE_NODE  temp;
115        UT_CAHCE_NODE* head;
116        UT_CAHCE_NODE  hash[_UT_HASH_DEPTH];
117} UT_CACHE;
118
119#ifdef _UT_USE_DYNAMIC_MALLOC_FREE
120UT_STATIC_API void ut_CacheUpdate(UT_FONT_MANAGER* fontManager)
121{
122        UT_CACHE* cache = fontManager->cache;
123        UT_CAHCE_NODE* p = cache->head->gPrev;
124        UT_CAHCE_NODE* temp;
125        while (p!=cache->head && (cache->usedMemorySize > (cache->memorySize*2/3)))
126        {
127                temp = p->gPrev;
128                p->lPrev->lNext = p->lNext;
129                p->lNext->lPrev = p->lPrev;
130                p->gPrev->gNext = p->gNext;
131                p->gNext->gPrev = p->gPrev;
132                fontManager->FreeMemory(p);
133                cache->usedMemorySize -= sizeof(UT_CAHCE_NODE) + p->lSize;
134                p = temp;
135        }
136}
137#else /*#ifdef _UT_USE_DYNAMIC_MALLOC_FREE*/
138UT_STATIC_API void ut_CacheUpdate(UT_FONT_MANAGER* fontManager)
139{
140        int i;
141        UT_CACHE* cache;
142        cache = fontManager->cache;
143        cache->usedMemorySize = sizeof(UT_CACHE);
144        cache->head           = &cache->temp;
145        cache->head->gPrev    = cache->head->gNext = cache->head;
146        for (i=0; i<_UT_HASH_DEPTH; i++)
147        {
148                cache->hash[i].lPrev = cache->hash[i].lNext = &cache->hash[i];
149        }
150}
151#endif /*#ifdef _UT_USE_DYNAMIC_MALLOC_FREE*/
152
153UT_STATIC_API UT_BOOL utm_CacheHit(UT_FC* fc, UT_CODE code, UT_IMAGE* image)
154{
155        if (!fc->font.info.limit)
156        {
157                UT_CACHE* cache = fc->task->fontManager->cache;
158                if (cache)
159                {
160                        UT_U32 identifier0 = ut_GetFcIdentifier0(fc);
161                        UT_U32 identifier1 = ut_GetFcIdentifier1(fc);
162                        UT_U32 identifier2 = ut_GetFcIdentifier2(fc, code);
163                        int i = ut_GetHashIndex(identifier0, identifier1, identifier2);
164                        UT_CAHCE_NODE* p;
165                        for (p=cache->hash[i].lNext; p!=&cache->hash[i]; p=p->lNext)
166                        {
167                                if ((p->fontID      == fc->font.info.id) &&
168                                        (p->identifier0 == identifier0) &&
169                                        (p->identifier1 == identifier1) &&
170                                        (p->identifier2 == identifier2))
171                                {
172                                        p->gPrev->gNext = p->gNext;
173                                        p->gNext->gPrev = p->gPrev;
174                                        p->gPrev = cache->head;
175                                        p->gNext = cache->head->gNext;
176                                        cache->head->gNext->gPrev = p;
177                                        cache->head->gNext = p;
178                                        image->bbox   = p->bbox;
179                                        image->width  = p->width;
180                                        image->height = p->height;
181                                        image->bSize  = p->bSize;
182                                        image->lSize  = p->lSize;
183                                        image->type   = p->type;
184                                        image->data = (unsigned char*)(p+1);
185                                        return _UT_TRUE;
186                                }
187                        }
188                }
189        }
190        return _UT_FALSE;
191}
192
193UT_STATIC_API void utm_CacheAdd(UT_FC* fc, UT_CODE code, UT_IMAGE* image)
194{
195        UT_FONT_MANAGER* fontManager = fc->task->fontManager;
196        UT_CACHE* cache = fontManager->cache;
197        if (cache)
198        {
199                UT_U32 identifier0;
200                UT_U32 identifier1;
201                UT_U32 identifier2;
202                UT_CAHCE_NODE* head;
203                UT_CAHCE_NODE* p;
204                int size = sizeof(UT_CAHCE_NODE) + (image->lSize+3)&~3;
205                if ((cache->usedMemorySize + size) > cache->memorySize)
206                {
207                        ut_CacheUpdate(fontManager);
208                }
209#ifdef _UT_USE_DYNAMIC_MALLOC_FREE
210                p = (UT_CAHCE_NODE*)fontManager->AllocMemory(size);
211                if (!p) return;
212#else /*#ifdef _UT_USE_DYNAMIC_MALLOC_FREE*/
213                p = (UT_CAHCE_NODE*)&cache->staticBuffer[cache->usedMemorySize];
214#endif /*#ifdef _UT_USE_DYNAMIC_MALLOC_FREE*/
215                cache->usedMemorySize += size;
216                identifier0 = ut_GetFcIdentifier0(fc);
217                identifier1 = ut_GetFcIdentifier1(fc);
218                identifier2 = ut_GetFcIdentifier2(fc, code);
219                head = &cache->hash[ut_GetHashIndex(identifier0, identifier1, identifier2)];
220                UT_MEMCPY(p+1, image->data, image->lSize);
221                p->fontID      = fc->font.info.id;
222                p->identifier0 = identifier0;
223                p->identifier1 = identifier1;
224                p->identifier2 = identifier2;
225                p->bbox        = image->bbox;
226                p->width       = image->width;
227                p->height      = image->height;
228                p->bSize       = image->bSize;
229                p->lSize       = image->lSize;
230                p->type        = image->type;
231                p->lPrev = head;
232                p->lNext = head->lNext;
233                head->lNext->lPrev = p;
234                head->lNext = p;
235                p->gPrev = cache->head;
236                p->gNext = cache->head->gNext;
237                cache->head->gNext->gPrev = p;
238                cache->head->gNext = p;
239        }
240}
241
242void utm_CacheInit(UT_FONT_MANAGER* fontManager, void* staticBuffer, int memorySize, int lowestSize, int highestSize)
243{
244        int i;
245        UT_CACHE* cache;
246#ifdef _UT_USE_DYNAMIC_MALLOC_FREE
247        cache = fontManager->cache = (UT_CACHE*)fontManager->AllocMemory(sizeof(UT_CACHE));
248        cache->staticBuffer = 0;
249        cache->usedMemorySize = 0;
250#else /*#ifdef _UT_USE_DYNAMIC_MALLOC_FREE*/
251#ifdef _UT_USE_MALLOC_FREE
252        staticBuffer = fontManager->AllocMemory(sizeof(UT_CACHE) + sizeof(UT_CAHCE_NODE)*200 + memorySize);
253        if (!staticBuffer || (memorySize < (sizeof(UT_CACHE) + sizeof(UT_CAHCE_NODE)*200)))
254        {
255                staticBuffer = 0;
256                return;
257        }
258#else /*#ifdef _UT_USE_MALLOC_FREE*/
259        unsigned long align = ((unsigned long)staticBuffer) & 3;
260        if (align)
261        {
262                char* p = (char*)staticBuffer;
263                p += 4 - align;
264                staticBuffer = p;
265        }
266        if (!staticBuffer || (memorySize < (sizeof(UT_CACHE) + sizeof(UT_CAHCE_NODE)*200))) return;
267#endif /*#ifdef _UT_USE_MALLOC_FREE*/
268        cache = fontManager->cache = (UT_CACHE*)staticBuffer;
269        cache->staticBuffer = (char*)staticBuffer;
270        cache->usedMemorySize = sizeof(UT_CACHE);
271#endif /*#ifdef _UT_USE_DYNAMIC_MALLOC_FREE*/
272        cache->memorySize     = memorySize;
273        cache->lowestSize     = lowestSize;
274        cache->highestSize    = highestSize;
275        cache->head           = &cache->temp;
276        cache->head->gPrev    = cache->head->gNext = cache->head;
277        for (i=0; i<_UT_HASH_DEPTH; i++)
278        {
279                cache->hash[i].lPrev = cache->hash[i].lNext = &cache->hash[i];
280        }
281}
282
283void utm_CacheTerm(UT_FONT_MANAGER* fontManager)
284{
285        UT_CACHE* cache = fontManager->cache;
286        if (cache)
287        {
288#ifdef _UT_USE_DYNAMIC_MALLOC_FREE
289                int i;
290                UT_CAHCE_NODE* p;
291                UT_CAHCE_NODE* n;
292                for (i=0; i<_UT_HASH_DEPTH; i++)
293                {
294                        for (p=cache->hash[i].lNext; p!=&cache->hash[i]; p=n)
295                        {
296                                n = p->lNext;
297                                p->lNext->lPrev = p->lPrev;
298                                p->lPrev->lNext = p->lNext;
299                                fontManager->FreeMemory(p);
300                        }
301                }
302                fontManager->FreeMemory(cache);
303#else /*#ifdef _UT_USE_DYNAMIC_MALLOC_FREE*/
304#ifdef _UT_USE_MALLOC_FREE
305                if (cache->staticBuffer)
306                {
307                        fontManager->FreeMemory(cache->staticBuffer);
308                        cache->staticBuffer = 0;
309                }
310#endif /*#ifdef _UT_USE_MALLOC_FREE*/
311#endif /*#ifdef _UT_USE_DYNAMIC_MALLOC_FREE*/
312                fontManager->cache = 0;
313        }
314}
315
316#endif /*#ifdef _UT_USE_CACHE*/
317
318/***************************************************************************/
319
320typedef struct
321{
322    UT_U32  lo;
323    UT_I32  hi;
324} UT_I64;
325
326UT_STATIC_API void ut_Mul(UT_I32 multiplicand, UT_I32 multiplier, UT_I64* result)
327{
328        UT_U32 lo1 = multiplicand & 0x0000FFFFU;
329        UT_U32 hi1 = multiplicand >> 16;
330        UT_U32 lo2 = multiplier & 0x0000FFFFU;
331        UT_U32 hi2 = multiplier >> 16;
332        UT_U32 lo = lo1 * lo2;
333        UT_U32 i1 = lo1 * hi2;
334        UT_U32 i2 = lo2 * hi1;
335        UT_U32 hi = hi1 * hi2;
336        i1 += i2;
337        hi += (UT_U32)(i1 < i2) << 16;
338        hi += i1 >> 16;
339        i1  = i1 << 16;
340        lo += i1;
341        hi += (lo < i1);
342        result->hi = hi;
343        result->lo = lo;
344}
345
346UT_STATIC_API UT_I32 ut_Div(UT_I64 dividend, UT_U32 divisor)
347{
348        UT_U32 r = dividend.hi;
349        UT_U32 q = 0;
350        int i = 32;
351        if (r >= divisor) return 0x7FFFFFFFU;
352        do
353        {
354                r <<= 1;
355                q <<= 1;
356                r  |= dividend.lo >> 31;
357                if (r >= divisor)
358                {
359                        r -= divisor;
360                        q |= 1;
361                }
362                dividend.lo <<= 1;
363        } while (i--);
364        return q;
365}
366
367UT_STATIC_API UT_I32 ut_MulDiv(UT_I32 multiplicand, UT_I32 multiplier, UT_I32 divisor)
368{
369        UT_I32 s;
370        if (multiplier == divisor)
371        {
372                return multiplicand;
373        }
374        s  = multiplicand; multiplicand = (multiplicand < 0) ? -multiplicand : multiplicand;
375        s ^= multiplier; multiplier = (multiplier < 0) ? -multiplier : multiplier;
376        s ^= divisor; divisor = (divisor < 0) ? -divisor : divisor;
377        if ((multiplicand <= 46340) && (multiplier <= 46340) && (divisor <= 176095))
378        {
379                multiplicand = (multiplicand * multiplier + (divisor >> 1)) / divisor;
380                return (s < 0) ? -multiplicand : multiplicand;
381        }
382        else
383        {
384                UT_I64 dividend;
385                ut_Mul(multiplicand, multiplier, &dividend);
386                return ut_Div(dividend, divisor);
387        }
388}
389
390UT_STATIC_API UT_FIXED ut_MulFixed(UT_FIXED multiplicand, UT_FIXED multiplier)
391{
392        UT_I32 s;
393        UT_U32 ua, ub;
394        if (multiplier == 0x10000)
395        {
396                return multiplicand;
397        }
398        s  = multiplicand; multiplicand = (multiplicand < 0) ? -multiplicand : multiplicand;
399        s ^= multiplier; multiplier = (multiplier < 0) ? -multiplier : multiplier;
400        ua = (UT_U32)multiplicand;
401        ub = (UT_U32)multiplier;
402        if ((ua <= 2048) && (ub <= 1048576))
403        {
404                ua = (ua * ub + 0x8000) >> 16;
405        }
406        else
407        {
408                UT_U32 al = ua & 0xFFFF;
409                ua = (ua >> 16) * ub +  al * (ub >> 16) + ((al * (ub & 0xFFFF) + 0x8000) >> 16);
410        }
411        return (s < 0) ? -(UT_FIXED)ua : (UT_FIXED)ua;
412}
413
414UT_STATIC_API UT_FIXED ut_DivFixed(UT_FIXED dividend, UT_FIXED divisor)
415{
416        UT_I32 s;
417        UT_U32 q;
418        s  = dividend; dividend = (dividend < 0) ? -dividend : dividend;
419        s ^= divisor; divisor = (divisor < 0) ? -divisor : divisor;
420        if (dividend >> 16)
421        {
422                UT_I64 dividend64;
423                dividend64.hi = dividend >> 16;
424                dividend64.lo = dividend << 16;
425                q = ut_Div(dividend64, (UT_I32)divisor);
426        }
427        else
428        {
429                q = (UT_U32)((dividend << 16) + (divisor >> 1)) / (UT_U32)divisor;
430        }
431        return (s < 0) ? -(UT_FIXED)q : (UT_FIXED)q;
432}
433
434int ut_DecryptNum(UT_POINTER* w)
435{
436        int num;
437    num = *w->i8++;
438    if (num == -128)
439        {
440                num = (w->i8[0] << 8) | w->u8[1];
441                w->i16++;
442        }
443    else if (num >= 123)
444        {
445                num = ((num - 123) << 8) + (int)(*w->u8++) + 123;
446        }
447    else if (num <= -123)
448        {
449                num = ((num + 123) << 8) - (int)(*w->u8++) - 123;
450        }
451    return num;
452}
453
454#define _X_TOUCHED_BY_STEM_CONTROL      0x01
455#define _Y_TOUCHED_BY_STEM_CONTROL      0x02
456
457UT_STATIC_API void ut_Shift(int p1, int p2, int p, UT_I32* original, UT_COORD* hinted)
458{
459        int i;
460        UT_COORD  d;
461        d = hinted[p] - original[p];
462        for (i=p1; i<p; i++)
463        {
464                hinted[i] += d;
465        }
466        for (i=p+1; i<=p2; i++)
467        {
468                hinted[i] += d;
469        }
470}
471
472UT_STATIC_API void itrp_IUP(UT_FONT_TASK* task, UT_I32* original, UT_COORD* hinted, UT_U8 touchedMask)
473{
474    UT_U8* touched = task->workGlyph.touched;
475    UT_I32 *ref;
476    UT_I32 *stop;
477    UT_I32 *originalEnd;
478    UT_I32 refCoord1;
479    UT_I32 refCoord2;
480    UT_I32 refBase;
481    UT_I32 refDelta;
482    UT_I32 refDelta2;
483    UT_COORD *cur;
484    UT_COORD curBase;
485    UT_COORD curOffset;
486    UT_COORD curDelta;
487    UT_I32 pointIndex;
488    UT_I32 startPointIndex;
489    UT_I32 endPointIndex;
490    UT_I32 stopPointIndex;
491    UT_I32 refPointIndex1;
492    UT_I32 refPointIndex2;
493    UT_I32 pathIndex;
494    UT_I32 temp;
495    UT_FIXED ratio;
496        UT_TRACE2("itrp_IUP(touchedMask=%d)", touchedMask);
497        UT_TRACE_TAB_INC();
498    for (pathIndex=0; pathIndex<task->workGlyph.nPath; pathIndex++)
499    {
500        startPointIndex = task->workGlyph.startPointIndex[pathIndex];
501        endPointIndex = task->workGlyph.endPointIndex[pathIndex];
502        originalEnd = &original[endPointIndex];
503        pointIndex = startPointIndex;
504        while (!(touched[pointIndex] & touchedMask) && (pointIndex <= endPointIndex)) pointIndex++;
505        if (pointIndex <= endPointIndex)
506        {
507            stopPointIndex = pointIndex;
508            do
509            {
510                do
511                {
512                    refPointIndex1 = pointIndex;
513                    pointIndex++;
514                    if (pointIndex > endPointIndex) pointIndex = startPointIndex;
515                } while ((touched[pointIndex] & touchedMask) && pointIndex != stopPointIndex);
516                if (pointIndex != stopPointIndex)
517                {
518                    refPointIndex2 = pointIndex;
519                    do
520                    {
521                        refPointIndex2++;
522                        if (refPointIndex2 > endPointIndex) refPointIndex2 = startPointIndex;
523                    } while (!(touched[refPointIndex2] & touchedMask));
524                    refCoord1 = original[refPointIndex1];
525                    refCoord2 = original[refPointIndex2];
526                    if (refCoord1 < refCoord2)
527                    {
528                        refBase = refCoord1;
529                        refDelta = refCoord2 - refCoord1;
530                                                curBase = hinted[refPointIndex1];
531                                                curOffset = hinted[refPointIndex2];
532                    }
533                    else
534                    {
535                        refBase = refCoord2;
536                        refDelta = refCoord1 - refCoord2;
537                                                curBase = hinted[refPointIndex2];
538                                                curOffset = hinted[refPointIndex1];
539                    }
540                    if (refDelta)
541                    {
542                                                UT_TRACE2("refPointIndex1 = %d)", refPointIndex1);
543                                                UT_TRACE2("refPointIndex2 = %d)", refPointIndex2);
544                                                UT_TRACE2("refBase        = %d)", refBase);
545                                                UT_TRACE2("refDelta       = %d)", refDelta);
546                                                UT_TRACE2("curBase        = %d)", curBase);
547                                                UT_TRACE2("curOffset      = %d)", curOffset);
548                        curDelta = curOffset - curBase;
549                        if (refDelta < 32768 && curDelta < 32768)
550                        {
551                                                        ref = &original[pointIndex];
552                            cur = &hinted[pointIndex];
553                            refDelta2 = refDelta >> 1;
554                            stop = &original[refPointIndex2];
555                            for (; ref<stop; ref++,cur++)
556                            {
557                                if ((*cur <= curBase) || (*cur >= curOffset)) continue;
558                                                                UT_TRACE2("    old = %d)", *cur);
559                                                                UT_TRACE2("    new = %d)", curBase + ((*ref-refBase) * curDelta + refDelta2) / refDelta);
560                                *cur = curBase + ((*ref-refBase) * curDelta + refDelta2) / refDelta;
561                            }
562                            while (ref != stop)
563                            {
564                                if ((*cur > curBase) && (*cur < curOffset))
565                                {
566                                                                        UT_TRACE2("    old = %d)", *cur);
567                                                                        UT_TRACE2("    new = %d)", curBase + ((*ref-refBase) * curDelta + refDelta2) / refDelta);
568                                    *cur = curBase + ((*ref-refBase) * curDelta + refDelta2) / refDelta;
569                                }
570                                ref++;
571                                cur++;
572                                if (ref > originalEnd)
573                                {
574                                    ref = &original[startPointIndex];
575                                    cur = &hinted[startPointIndex];
576                                }
577                            }
578                            pointIndex = refPointIndex2;
579                        }
580                        else
581                        {
582                            ratio = ut_DivFixed(curDelta, refDelta);
583                            while (pointIndex != refPointIndex2)
584                            {
585                                temp = hinted[pointIndex];
586                                if ((temp > curBase) && (temp < curOffset))
587                                {
588                                    temp = original[pointIndex];
589                                    temp -= refBase;
590                                    temp = ut_MulFixed(temp, ratio);
591                                                                        UT_TRACE2("    old = %d)", hinted[pointIndex]);
592                                                                        UT_TRACE2("    new = %d)", temp + curBase);
593                                                                        hinted[pointIndex] = temp + curBase;
594                                }
595                                if (pointIndex < endPointIndex) pointIndex++;
596                                else pointIndex = startPointIndex;
597                            }
598                        }
599                    }
600                    else
601                    {
602                        while (pointIndex != refPointIndex2)
603                        {
604                            if (pointIndex < endPointIndex) pointIndex++;
605                            else pointIndex = startPointIndex;
606                        }
607                    }
608                }
609            } while (pointIndex != stopPointIndex);
610        }
611    }
612        UT_TRACE_TAB_DEC();
613}
614
615#define ut_ScaleCoord(emSize, coord, gridFitSize) (((coord) << _UT_PIXEL_SHIFT) * (gridFitSize) / emSize)
616
617UT_STATIC_API UT_COORD itrp_RTG(int coord)
618{
619    UT_COORD value = coord;
620    if (value >= 0)
621    {
622        value += _UT_HALF_PIXEL;
623        value &= ~(_UT_ONE_PIXEL - 1);
624    }
625    else
626    {
627        value = -value;
628        value += _UT_HALF_PIXEL;
629        value &= ~(_UT_ONE_PIXEL - 1);
630        value = -value;
631    }
632    if (((coord ^ value)) < 0 && coord) value = 0;
633    return value;
634}
635
636UT_STATIC_API UT_COORD itrp_RTG_Gray(US_RASTER_DIR* dir, int coord)
637{
638    UT_COORD value = coord;
639    if (value >= 0)
640    {
641        value += dir->graySubHalf;
642        value &= ~dir->graySubPix;
643    }
644    else
645    {
646        value = -value;
647        value += dir->graySubHalf;
648        value &= ~dir->graySubPix;
649        value = -value;
650    }
651    if (((coord ^ value)) < 0 && coord) value = 0;
652    return value;
653}
654
655UT_STATIC_API void itrp_STEM(UT_FONT_TASK* task, US_RASTER_DIR* dir, UT_POINTER* w, int offset)
656{
657        int i;
658        int snap_pos_adjust = 0;
659    UT_COORD original_b;
660    UT_COORD original_o;
661    UT_COORD hinted_b;
662    UT_COORD hinted_o;
663        UT_GS* gs = &task->gs;
664        UT_TRACE2("itrp_STEM(touchedMask=%d)", dir->touchedMask);
665        UT_TRACE_TAB_INC();
666    original_b = ut_DecryptNum(w) + offset;
667    original_o = ut_DecryptNum(w) + original_b;
668        UT_TRACE2("original_b = %d", original_b);
669        UT_TRACE2("original_o = %d", original_o);
670        original_b = ut_ScaleCoord(task->emSize, original_b, dir->gridFitSize);
671        original_o = ut_ScaleCoord(task->emSize, original_o, dir->gridFitSize);
672        UT_TRACE2("original_b = %d", original_b);
673        UT_TRACE2("original_o = %d", original_o);
674        if (gs->snapPosCutIn)
675        {
676                int snap_pos_ci = gs->snapPosCutIn << dir->grayPreShift;
677                snap_pos_adjust = ut_ScaleCoord(task->emSize, gs->snapPos, dir->gridFitSize);
678                snap_pos_adjust -= original_b;
679                if (snap_pos_adjust > 0)
680                {
681                        if (snap_pos_adjust > snap_pos_ci) snap_pos_adjust = 0;
682                }
683                else
684                {
685                        if (-snap_pos_adjust > snap_pos_ci) snap_pos_adjust = 0;
686                }
687        }
688        UT_TRACE2("original_b = %d", original_b);
689        UT_TRACE2("original_o = %d", original_o);
690        UT_TRACE2("snap_pos_adjust = %d", snap_pos_adjust);
691        if (dir->isGray)
692        {
693                hinted_b = itrp_RTG_Gray(dir, original_b + snap_pos_adjust);
694                hinted_o = itrp_RTG_Gray(dir, original_o + snap_pos_adjust);
695                if (original_b < original_o)
696                {
697                        UT_COORD stem_depth = original_o - original_b;
698                        UT_TRACE2("stem_depth = %d", stem_depth);
699                        if (gs->snapStemCutIn && gs->snapStem)
700                        {
701                                int snap_stem = ut_ScaleCoord(task->emSize, gs->snapStem, dir->gridFitSize);
702                                int snap_stem_ci = gs->snapStemCutIn << dir->grayPreShift;
703                                if ((stem_depth >= (snap_stem-snap_stem_ci)) && (stem_depth <= (snap_stem+snap_stem_ci)))
704                                {
705                                        stem_depth = snap_stem;
706                                        UT_TRACE2("SW(stem_depth) = %d", stem_depth);
707                                }
708                        }
709                        stem_depth = itrp_RTG(stem_depth);
710                        if (!stem_depth) stem_depth = dir->graySubPix + 1;
711                        hinted_o = hinted_b + stem_depth;
712                }
713                else
714                {
715                        UT_COORD stem_depth = original_b - original_o;
716                        UT_TRACE2("stem_depth = %d", stem_depth);
717                        if (gs->snapStemCutIn && gs->snapStem)
718                        {
719                                int snap_stem = ut_ScaleCoord(task->emSize, gs->snapStem, dir->gridFitSize);
720                                if ((stem_depth > (snap_stem-gs->snapStemCutIn)) && (stem_depth < (snap_stem+gs->snapStemCutIn)))
721                                {
722                                        stem_depth = snap_stem;
723                                        UT_TRACE2("SW(stem_depth) = %d", stem_depth);
724                                }
725                        }
726                        stem_depth = itrp_RTG(stem_depth);
727                        if (!stem_depth) stem_depth = dir->graySubPix + 1;
728                        hinted_o = hinted_b - stem_depth;
729                }
730        }
731        else
732        {
733                hinted_b = itrp_RTG(original_b + snap_pos_adjust);
734                hinted_o = itrp_RTG(original_o + snap_pos_adjust);
735                if (original_b < original_o)
736                {
737                        UT_COORD stem_depth = original_o - original_b;
738                        UT_TRACE2("stem_depth = %d", stem_depth);
739                        if (gs->snapStemCutIn && gs->snapStem)
740                        {
741                                int snap_stem = ut_ScaleCoord(task->emSize, gs->snapStem, dir->gridFitSize);
742                                if ((stem_depth > (snap_stem-gs->snapStemCutIn)) && (stem_depth < (snap_stem+gs->snapStemCutIn)))
743                                {
744                                        stem_depth = snap_stem;
745                                        UT_TRACE2("SW(stem_depth) = %d", stem_depth);
746                                }
747                        }
748                        stem_depth = itrp_RTG(stem_depth);
749                        if (!stem_depth) stem_depth = _UT_ONE_PIXEL;
750                        hinted_o = hinted_b + stem_depth;
751                }
752                else
753                {
754                        UT_COORD stem_depth = original_b - original_o;
755                        UT_TRACE2("stem_depth = %d", stem_depth);
756                        if (gs->snapStemCutIn && gs->snapStem)
757                        {
758                                int snap_stem = ut_ScaleCoord(task->emSize, gs->snapStem, dir->gridFitSize);
759                                if ((stem_depth > (snap_stem-gs->snapStemCutIn)) && (stem_depth < (snap_stem+gs->snapStemCutIn)))
760                                {
761                                        stem_depth = snap_stem;
762                                        UT_TRACE2("SW(stem_depth) = %d", stem_depth);
763                                }
764                        }
765                        stem_depth = itrp_RTG(stem_depth);
766                        if (!stem_depth) stem_depth = _UT_ONE_PIXEL;
767                        hinted_o = hinted_b - stem_depth;
768                }
769        }
770        UT_TRACE2("hinted_b = %d", hinted_b);
771        UT_TRACE2("hinted_o = %d", hinted_o);
772        for (i=0; i<task->workGlyph.nPoint; i++)
773        {
774                if (dir->original[i] == original_b)
775                {
776                        UT_TRACE2("base match[%d]", i);
777                        UT_TRACE2("    old = %d", dir->hinted[i]);
778                        UT_TRACE2("    new = %d", hinted_b);
779                        dir->hinted[i] = hinted_b;
780                        task->workGlyph.touched[i] |= dir->touchedMask;
781                }
782                else if (dir->original[i] == original_o)
783                {
784                        UT_TRACE2("offset match[%d]", i);
785                        UT_TRACE2("    old = %d", dir->hinted[i]);
786                        UT_TRACE2("    new = %d", hinted_o);
787                        dir->hinted[i] = hinted_o;
788                        task->workGlyph.touched[i] |= dir->touchedMask;
789                }
790        }
791        UT_TRACE_TAB_DEC();
792}
793
794UT_STATIC_API void itrp_POINT(UT_FONT_TASK* task, US_RASTER_DIR* dir, UT_POINTER* w, int offset)
795{
796        int i;
797        int snap_pos_adjust = 0;
798    UT_COORD original_b;
799    UT_COORD hinted_b;
800        UT_GS* gs = &task->gs;
801        UT_TRACE2("itrp_POINT(touchedMask=%d)", dir->touchedMask);
802        UT_TRACE_TAB_INC();
803    original_b = ut_DecryptNum(w) + offset;
804        original_b = ut_ScaleCoord(task->emSize, original_b, dir->gridFitSize);
805        if (gs->snapPosCutIn)
806        {
807                int snap_pos_ci = gs->snapPosCutIn << dir->grayPreShift;
808                snap_pos_adjust = ut_ScaleCoord(task->emSize, gs->snapPos, dir->gridFitSize);
809                snap_pos_adjust -= original_b;
810                if (snap_pos_adjust > 0)
811                {
812                        if (snap_pos_adjust > snap_pos_ci) snap_pos_adjust = 0;
813                }
814                else
815                {
816                        if (-snap_pos_adjust > snap_pos_ci) snap_pos_adjust = 0;
817                }
818        }
819        UT_TRACE2("original_b = %d", original_b);
820        UT_TRACE2("snap_pos_adjust = %d", snap_pos_adjust);
821        if (dir->isGray)
822        {
823                hinted_b = itrp_RTG_Gray(dir, original_b + snap_pos_adjust);
824        }
825        else
826        {
827                hinted_b = itrp_RTG(original_b + snap_pos_adjust);
828        }
829        UT_TRACE2("hinted_b = %d", hinted_b);
830        for (i=0; i<task->workGlyph.nPoint; i++)
831        {
832                if (dir->original[i] == original_b)
833                {
834                        UT_TRACE2("base match[%d]", i);
835                        UT_TRACE2("    old = %d", dir->hinted[i]);
836                        UT_TRACE2("    new = %d", hinted_b);
837                        dir->hinted[i] = hinted_b;
838                        task->workGlyph.touched[i] |= dir->touchedMask;
839                }
840        }
841        UT_TRACE_TAB_DEC();
842}
843
844#define ut_IsRootGlyphNull(task) !task->rootGlyph.nPoint
845#define ut_IsWorkGlyphNull(task) !task->workGlyph.nPoint
846#define ut_NewPath(task) task->workGlyph.startPointIndex[task->workGlyph.nPath] = task->workGlyph.nPoint
847#define ut_EndPath(task) task->workGlyph.endPointIndex[task->workGlyph.nPath++] = task->workGlyph.nPoint-1
848
849UT_STATIC_API void ut_NewGlyph(UT_FONT_TASK* task)
850{
851        UT_TRACE1("ut_NewGlyph()");
852    task->workGlyph.startPointIndex     += task->workGlyph.nPath;
853    task->workGlyph.endPointIndex       += task->workGlyph.nPath;
854    task->workGlyph.x                   += task->workGlyph.nPoint;
855    task->workGlyph.y                   += task->workGlyph.nPoint;
856    task->workGlyph.on                  += task->workGlyph.nPoint;
857    task->workGlyph.touched             += task->workGlyph.nPoint;
858    task->workGlyph.ox                  += task->workGlyph.nPoint;
859    task->workGlyph.oy                  += task->workGlyph.nPoint;
860    task->workGlyph.nPath  = 0;
861    task->workGlyph.nPoint = 0;
862}
863
864UT_STATIC_API void ut_EndGlyph(UT_FONT_TASK* task)
865{
866    int i;
867        UT_TRACE1("ut_EndGlyph()");
868    for (i=0; i<task->workGlyph.nPath; i++)
869    {
870        task->workGlyph.startPointIndex[i] += task->rootGlyph.nPoint;
871        task->workGlyph.endPointIndex[i]   += task->rootGlyph.nPoint;
872    }
873    task->rootGlyph.nPath  += task->workGlyph.nPath;
874    task->rootGlyph.nPoint += task->workGlyph.nPoint;
875}
876
877UT_STATIC_API void ut_AddPoint(UT_FONT_TASK* task, int x, int y, int on)
878{
879        UT_TRACE2("ut_AddPoint(%d)", task->workGlyph.nPoint);
880        UT_TRACE2("    x = %d", x);
881        UT_TRACE2("    y = %d", y);
882        UT_TRACE2("   on = %d", on);
883    task->workGlyph.x[task->workGlyph.nPoint] = task->workGlyph.ox[task->workGlyph.nPoint] = ut_ScaleCoord(task->emSize, x, task->xDir.gridFitSize);
884    task->workGlyph.y[task->workGlyph.nPoint] = task->workGlyph.oy[task->workGlyph.nPoint] = ut_ScaleCoord(task->emSize, y, task->yDir.gridFitSize);
885    task->workGlyph.on[task->workGlyph.nPoint] = on;
886    task->workGlyph.touched[task->workGlyph.nPoint] = 0;
887        UT_TRACE2("    scaled_x = %d", task->workGlyph.ox[task->workGlyph.nPoint]);
888        UT_TRACE2("    scaled_y = %d", task->workGlyph.oy[task->workGlyph.nPoint]);
889    task->workGlyph.nPoint++;
890}
891
892UT_STATIC_API void itrp_STROKE(UT_FONT_TASK* task, US_RASTER_DIR* dir, UT_POINTER* w, int offset)
893{
894        if (dir->isGray)
895        {
896                int i;
897                for (i=0; i<task->workGlyph.nPoint; i++)
898                {
899                        dir->hinted[i] = itrp_RTG_Gray(dir, dir->hinted[i]);
900                        task->workGlyph.touched[i] |= dir->touchedMask;
901                }
902        }
903}
904
905UT_STATIC_API UT_BOOL ut_InterpreteSimpleGlyph(UT_FONT_TASK* task, UT_CMAP* cmap, UT_POINTER w, UT_BOOL applyHint, int xOffset)
906{
907    UT_U8 f;
908    int i, count;
909    int x = xOffset;
910    int y = 0;
911    UT_BOOL first = _UT_TRUE;
912    UT_U8* op;
913        UT_TRACE1("ut_InterpreteSimpleGlyph()");
914        UT_TRACE_TAB_INC();
915        count = ut_DecryptNum(&w);
916        op = w.u8;
917        w.p += (count + 1) >> 1;
918    ut_NewGlyph(task);
919    for (i=0;;)
920    {
921        f = *op >> 4;
922        if (f & _UT_POINT_MASK_HAS_X)
923        {
924            x += ut_DecryptNum(&w);
925        }
926        if (f & _UT_POINT_MASK_HAS_Y)
927        {
928            y += ut_DecryptNum(&w);
929        }
930        if (f & _UT_POINT_MASK_IS_START)
931        {
932            if (first) first = _UT_FALSE;
933            else       ut_EndPath(task);
934            ut_NewPath(task);
935        }
936        ut_AddPoint(task, x, y, f & _UT_POINT_MASK_IS_ON);
937        i++; if (i == count) break;
938        f = *op++ & 15;
939        if (f & _UT_POINT_MASK_HAS_X)
940        {
941            x += ut_DecryptNum(&w);
942        }
943        if (f & _UT_POINT_MASK_HAS_Y)
944        {
945            y += ut_DecryptNum(&w);
946        }
947        if (f & _UT_POINT_MASK_IS_START)
948        {
949            if (first) first = _UT_FALSE;
950            else       ut_EndPath(task);
951            ut_NewPath(task);
952        }
953        ut_AddPoint(task, x, y, f & _UT_POINT_MASK_IS_ON);
954        i++; if (i == count) break;
955    }
956    ut_EndPath(task);
957    if (!ut_IsWorkGlyphNull(task))
958    {
959                if (cmap->isStroke)
960                {
961                        US_RASTER_DIR* xDir = &task->xDir;
962                        US_RASTER_DIR* yDir = &task->yDir;
963                        xDir->touchedMask = _X_TOUCHED_BY_STEM_CONTROL;
964                        yDir->touchedMask = _Y_TOUCHED_BY_STEM_CONTROL;
965                        xDir->original    = task->workGlyph.ox;
966                        yDir->original    = task->workGlyph.oy;
967                        xDir->hinted      = task->workGlyph.x;
968                        yDir->hinted      = task->workGlyph.y;
969                        itrp_STROKE(task, xDir, &w, xOffset);
970                        itrp_STROKE(task, yDir, &w, 0);
971                        itrp_IUP(task, task->workGlyph.ox, task->workGlyph.x, _X_TOUCHED_BY_STEM_CONTROL);
972                        itrp_IUP(task, task->workGlyph.oy, task->workGlyph.y, _Y_TOUCHED_BY_STEM_CONTROL);
973                }
974                else if (applyHint)
975                {
976                        US_RASTER_DIR* xDir = &task->xDir;
977                        US_RASTER_DIR* yDir = &task->yDir;
978                        int vTouched = 0;
979                        int hTouched = 0;
980                        UT_GS* gs = &task->gs;
981                        UT_MEMSET(gs, 0, sizeof(UT_GS));
982                        xDir->touchedMask = _X_TOUCHED_BY_STEM_CONTROL;
983                        yDir->touchedMask = _Y_TOUCHED_BY_STEM_CONTROL;
984                        xDir->original    = task->workGlyph.ox;
985                        yDir->original    = task->workGlyph.oy;
986                        xDir->hinted      = task->workGlyph.x;
987                        yDir->hinted      = task->workGlyph.y;
988                        for (;;)
989                        {
990                                f = *w.u8++;
991                                if (f == _UT_HINT_END) break;
992                                switch (f)
993                                {
994                                        case _UT_HINT_V_STEM:
995                                                vTouched = 1;
996                                                itrp_STEM(task, xDir, &w, xOffset);
997                                                break;
998                                        case _UT_HINT_H_STEM:
999                                                hTouched = 1;
1000                                                itrp_STEM(task, yDir, &w, 0);
1001                                                break;
1002                                        case _UT_HINT_V_POINT:
1003                                                vTouched = 1;
1004                                                itrp_POINT(task, xDir, &w, xOffset);
1005                                                break;
1006                                        case _UT_HINT_H_POINT:
1007                                                hTouched = 1;
1008                                                itrp_POINT(task, yDir, &w, 0);
1009                                                break;
1010                                        case _UT_HINT_SSP:
1011                                                gs->snapPos = ut_DecryptNum(&w);
1012                                                UT_TRACE2("SetSnapPosPositin(%d)", gs->snapPos);
1013                                                break;
1014                                        case _UT_HINT_SSPCI:
1015                                                gs->snapPosCutIn = ut_DecryptNum(&w);
1016                                                UT_TRACE2("SetSnapPosPositinCutIn(%d)", gs->snapPosCutIn);
1017                                                break;
1018                                        case _UT_HINT_SSD:
1019                                                gs->snapStem = ut_DecryptNum(&w);
1020                                                UT_TRACE2("SetSnapPosDepth(%d)", gs->snapStem);
1021                                                break;
1022                                        case _UT_HINT_SSDCI:
1023                                                gs->snapStemCutIn = ut_DecryptNum(&w);
1024                                                UT_TRACE2("SetSnapPosDepthCutIn(%d)", gs->snapStemCutIn);
1025                                                break;
1026                                }
1027                        }
1028                        if (vTouched) itrp_IUP(task, task->workGlyph.ox, task->workGlyph.x, _X_TOUCHED_BY_STEM_CONTROL);
1029                        if (hTouched) itrp_IUP(task, task->workGlyph.oy, task->workGlyph.y, _Y_TOUCHED_BY_STEM_CONTROL);
1030                }
1031        ut_EndGlyph(task);
1032    }
1033        UT_TRACE_TAB_DEC();
1034    return _UT_TRUE;
1035}
1036
1037UT_STATIC_API UT_BOOL ut_InterpreteGlyph(UT_FC* fc)
1038{
1039        int i = fc->glyph->count - 1;
1040        UT_TRACE1("ut_InterpreteGlyph()");
1041        UT_TRACE_TAB_INC();
1042    for (; i>=0; i--)
1043    {
1044        if (!ut_InterpreteSimpleGlyph(fc->task, fc->glyph->cmap, fc->glyph->data[i].p, !fc->preventHint, fc->glyph->data[i].xOffset)) return _UT_FALSE;
1045    }
1046        if (fc->task->emulItalic)
1047        {
1048                int i;
1049                for (i=0; i<fc->task->rootGlyph.nPoint; i++)
1050                {
1051                        fc->task->rootGlyph.x[i] += ut_ItalicY(fc->task->rootGlyph.y[i]);
1052                }
1053                fc->task->emulItalic = 0;
1054        }
1055        UT_TRACE_TAB_DEC();
1056    return _UT_TRUE;
1057}
1058
1059/***************************************************************************/
1060
1061typedef struct US_EDGE
1062{
1063    UT_I16           pos;
1064    UT_I16           dir;
1065    struct US_EDGE* next;
1066} US_EDGE;
1067
1068#ifdef _UT_USE_OLD_SCAN_CONVERSION
1069
1070UT_STATIC_API void ut_CalcScanBufferSize(UT_FONT_TASK* task)
1071{
1072        int horiEdgeCount = 0;
1073        int vertEdgeCount = 0;
1074        UT_COORD* x, px, cx;
1075        UT_COORD* y, py, cy;
1076        UT_COORD* stop;
1077        int iPath, iStartPoint, iEndPoint;
1078        for (iPath=0; iPath<task->rootGlyph.nPath; iPath++)
1079        {
1080                iStartPoint = task->rootGlyph.startPointIndex[iPath];
1081                iEndPoint   = task->rootGlyph.endPointIndex[iPath];
1082                if (iStartPoint == iEndPoint) continue;
1083                x = &task->rootGlyph.x[iStartPoint];
1084                y = &task->rootGlyph.y[iStartPoint];
1085                stop = &task->rootGlyph.x[iEndPoint];
1086                px = *x++;
1087                py = *y++;
1088                while (x <= stop)
1089                {
1090                        cx = *x++;
1091                        cy = *y++;
1092                        if (py > cy)
1093                        {
1094                                horiEdgeCount += ((py+_UT_ONE_PIXEL-1) >> _UT_PIXEL_SHIFT) - (cy >> _UT_PIXEL_SHIFT);
1095                        }
1096                        else
1097                        {
1098                                horiEdgeCount += ((cy+_UT_ONE_PIXEL-1) >> _UT_PIXEL_SHIFT) - (py >> _UT_PIXEL_SHIFT);
1099                        }
1100                        if (px > cx)
1101                        {
1102                                vertEdgeCount += ((px+_UT_ONE_PIXEL-1) >> _UT_PIXEL_SHIFT) - (cx >> _UT_PIXEL_SHIFT);
1103                        }
1104                        else
1105                        {
1106                                vertEdgeCount += ((cx+_UT_ONE_PIXEL-1) >> _UT_PIXEL_SHIFT) - (px >> _UT_PIXEL_SHIFT);
1107                        }
1108                        px = cx;
1109                        py = cy;
1110                }
1111                cx = task->rootGlyph.x[iStartPoint];
1112                cy = task->rootGlyph.y[iStartPoint];
1113                if (py > cy)
1114                {
1115                        horiEdgeCount += ((py+_UT_ONE_PIXEL-1) >> _UT_PIXEL_SHIFT) - (cy >> _UT_PIXEL_SHIFT);
1116                }
1117                else
1118                {
1119                        horiEdgeCount += ((cy+_UT_ONE_PIXEL-1) >> _UT_PIXEL_SHIFT) - (py >> _UT_PIXEL_SHIFT);
1120                }
1121                if (px > cx)
1122                {
1123                        vertEdgeCount += ((px+_UT_ONE_PIXEL-1) >> _UT_PIXEL_SHIFT) - (cx >> _UT_PIXEL_SHIFT);
1124                }
1125                else
1126                {
1127                        vertEdgeCount += ((cx+_UT_ONE_PIXEL-1) >> _UT_PIXEL_SHIFT) - (px >> _UT_PIXEL_SHIFT);
1128                }
1129        }
1130        task->horiScanBufferSize = sizeof(US_EDGE) * (task->i_ySize+horiEdgeCount);
1131        if (task->isDropout)
1132        {
1133                task->vertScanBufferSize = sizeof(US_EDGE) * (task->i_xSize+vertEdgeCount);
1134        }
1135        else
1136        {
1137                task->vertScanBufferSize = 0;
1138        }
1139#ifdef _UT_DEBUG
1140        task->horiEdgeCount = 0;
1141        task->vertEdgeCount = 0;
1142        task->horiEdgeTotalCount = horiEdgeCount;
1143        if (task->isDropout)
1144        {
1145                task->vertEdgeTotalCount = vertEdgeCount;
1146        }
1147#endif
1148}
1149
1150UT_STATIC_API void ut_PrepareScan(UT_FONT_TASK* task)
1151{
1152        int line;
1153    US_EDGE* edge = (US_EDGE*)task->edge;
1154    task->horiScanLine = edge;
1155        line = task->i_ySize;
1156    for (line--; line>=0; line--,edge++)
1157    {
1158        edge->pos  = 0;
1159        edge->dir  = 0;
1160        edge->next = 0;
1161    }
1162        if (task->isDropout)
1163        {
1164                task->vertScanLine = edge;
1165                line = task->i_xSize;
1166                for (line--; line>=0; line--,edge++)
1167                {
1168                        edge->pos  = 0;
1169                        edge->dir  = 0;
1170                        edge->next = 0;
1171                }
1172        }
1173        task->emptyEdge = edge;
1174}
1175
1176UT_STATIC_API void ut_AddHoriEdge(UT_FONT_TASK* task, int line, int pos, int dir)
1177{
1178        int i = task->horiScanLine[line].pos;
1179    US_EDGE* curr = &task->horiScanLine[line];
1180#ifdef _UT_DEBUG
1181    if ((line < 0) || (line >= task->i_ySize))
1182    {
1183        UT_FATAL_ERROR("Horizontal line overflow !!!");
1184                return;
1185    }
1186        if (task->horiEdgeCount >= task->horiEdgeTotalCount)
1187        {
1188        UT_FATAL_ERROR("Horizontal edge overflow !!!");
1189                return;
1190        }
1191        task->horiEdgeCount++;
1192#endif
1193    for (; i; i--)
1194    {
1195        if (curr->next->pos <= pos) break;
1196        curr = curr->next;
1197    }
1198    task->emptyEdge->next  = curr->next;
1199    task->emptyEdge->pos   = pos;
1200    task->emptyEdge->dir   = dir;
1201    curr->next = task->emptyEdge++;
1202    task->horiScanLine[line].pos++;
1203}
1204
1205UT_STATIC_API void ut_AddVertEdge(UT_FONT_TASK* task, int line, int pos, int dir)
1206{
1207        int i = task->vertScanLine[line].pos;
1208    US_EDGE* curr = &task->vertScanLine[line];
1209#ifdef _UT_DEBUG
1210    if ((line < 0) || (line >= task->i_xSize))
1211    {
1212        UT_FATAL_ERROR("Vertical line overflow !!!");
1213        return;
1214    }
1215        if (task->vertEdgeCount >= task->vertEdgeTotalCount)
1216        {
1217        UT_FATAL_ERROR("Vertical edge overflow !!!");
1218        return;
1219        }
1220        task->vertEdgeCount++;
1221#endif
1222    for (; i; i--)
1223    {
1224        if (curr->next->pos <= pos) break;
1225        curr = curr->next;
1226    }
1227    task->emptyEdge->next  = curr->next;
1228    task->emptyEdge->pos   = pos;
1229    task->emptyEdge->dir   = dir;
1230    curr->next = task->emptyEdge++;
1231    task->vertScanLine[line].pos++;
1232        UT_TRACE2("ut_AddVertEdge(line = %d)", line);
1233        UT_TRACE2("                pos = %d", pos);
1234        UT_TRACE2("                dir = %d", dir);
1235}
1236
1237#define ut_AddHoriEdgeP(task, x, y) ut_AddHoriEdge(task, y, x, +1)
1238#define ut_AddHoriEdgeN(task, x, y) ut_AddHoriEdge(task, y, x, -1)
1239#define ut_AddVertEdgeP(task, x, y) ut_AddVertEdge(task, x, y, +1)
1240#define ut_AddVertEdgeN(task, x, y) ut_AddVertEdge(task, x, y, -1)
1241
1242UT_STATIC_API void ut_LineTo_Standard(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2)
1243{
1244    if ((task->o_cx == o_x2) && (task->o_cy == o_y2))
1245    {
1246        return;
1247    }
1248    if (task->emptyLastPoint)
1249        {
1250                task->emptyLastPoint = 0;
1251                task->o_lx = o_x2;
1252                task->o_ly = o_y2;
1253        }
1254        else
1255        {
1256                ut_CheckLastPoint(task, o_x2, o_y2);
1257        }
1258    task->o_px = task->o_cx;
1259    task->o_py = task->o_cy;
1260    task->o_cx = o_x2;
1261    task->o_cy = o_y2;
1262        if (o_x1 == o_x2)
1263        {
1264                if (o_y1 < o_y2)
1265                {
1266                        int xx = ut_ExceptionAbovePixel(o_x1);
1267                        int yy = ut_AbovePixel(o_y1);
1268                        int i = ut_BelowPixel(o_y2) - yy + 1;
1269                        for (; i; i--)
1270                        {
1271                                ut_AddHoriEdgeP(task, xx, yy);
1272                                yy++;
1273                        }
1274                }
1275                else /*if (o_y1 > o_y2)*/
1276                {
1277                        int xx = ut_AbovePixel(o_x1);
1278                        int yy = ut_BelowPixel(o_y1);
1279                        int i = yy - ut_AbovePixel(o_y2) + 1;
1280                        for (; i; i--)
1281                        {
1282                                ut_AddHoriEdgeN(task, xx, yy);
1283                                yy--;
1284                        }
1285                }
1286        }
1287        else if (o_y1 == o_y2)
1288        {
1289        }
1290        else if (o_x1 < o_x2)
1291        {
1292                if (o_y1 < o_y2)
1293                {
1294                        int dx = (o_x2-o_x1) << _UT_PIXEL_SHIFT;
1295                        int dy = (o_y2-o_y1) << _UT_PIXEL_SHIFT;
1296                        int xx = ut_AbovePixel(o_x1);
1297                        int yy = ut_AbovePixel(o_y1);
1298                        int i = ut_BelowPixel(o_x2) - xx + 1
1299                                  + ut_BelowPixel(o_y2) - yy + 1;
1300                        int q = ((o_x2-o_x1) * ut_AboveScanDelta(o_y1))
1301                                  - ((o_y2-o_y1) * ut_AboveScanDelta(o_x1));
1302                        for (; i; i--)
1303                        {
1304                                if (q > 0)
1305                                {
1306                                        xx++;
1307                                        q -= dy;           
1308                                }
1309                                else
1310                                {
1311                                        ut_AddHoriEdgeP(task, xx, yy);
1312                                        yy++;
1313                                        q += dx;
1314                                }
1315                        }
1316                }
1317                else /*if (o_y1 > o_y2)*/
1318                {
1319                        int dx = (o_x2-o_x1) << _UT_PIXEL_SHIFT;
1320                        int dy = (o_y1-o_y2) << _UT_PIXEL_SHIFT;
1321                        int xx = ut_AbovePixel(o_x1);
1322                        int yy = ut_BelowPixel(o_y1);
1323                        int i = ut_BelowPixel(o_x2) - xx + 1
1324                                  + yy - ut_AbovePixel(o_y2) + 1;
1325                        int q = ((o_x2-o_x1) * ut_BelowScanDelta(o_y1))
1326                                  - ((o_y1-o_y2) * ut_AboveScanDelta(o_x1)) + 1;
1327                        for (; i; i--)
1328                        {
1329                                if (q > 0)
1330                                {
1331                                        xx++;
1332                                        q -= dy;           
1333                                }
1334                                else
1335                                {
1336                                        ut_AddHoriEdgeN(task, xx, yy);
1337                                        yy--;
1338                                        q += dx;
1339                                }
1340                        }
1341                }
1342        }
1343        else /*if (o_x1 > o_x2)*/
1344        {
1345                if (o_y1 < o_y2)
1346                {
1347                        int dx = (o_x1-o_x2) << _UT_PIXEL_SHIFT;
1348                        int dy = (o_y2-o_y1) << _UT_PIXEL_SHIFT;
1349                        int xx = ut_BelowPixel(o_x1);
1350                        int yy = ut_AbovePixel(o_y1);
1351                        int i = xx - ut_AbovePixel(o_x2) + 1
1352                                  + ut_BelowPixel(o_y2) - yy + 1;
1353                        int q = ((o_x1-o_x2) * ut_AboveScanDelta(o_y1))
1354                                  - ((o_y2-o_y1) * ut_BelowScanDelta(o_x1)) + 1;
1355                        for (; i; i--)
1356                        {
1357                                if (q > 0)
1358                                {
1359                                        xx--;
1360                                        q -= dy;           
1361                                }
1362                                else
1363                                {
1364                                        ut_AddHoriEdgeP(task, xx+1, yy);
1365                                        yy++;
1366                                        q += dx;
1367                                }
1368                        }
1369                }
1370                else /*if (o_y1 > o_y2)*/
1371                {
1372                        int dx = (o_x1-o_x2) << _UT_PIXEL_SHIFT;
1373                        int dy = (o_y1-o_y2) << _UT_PIXEL_SHIFT;
1374                        int yy = ut_BelowPixel(o_y1);
1375                        int xx = ut_BelowPixel(o_x1);
1376                        int i = yy - ut_AbovePixel(o_y2) + 1
1377                                  + xx - ut_AbovePixel(o_x2) + 1;
1378                        int q = ((o_x1-o_x2) * ut_BelowScanDelta(o_y1))
1379                                  - ((o_y1-o_y2) * ut_BelowScanDelta(o_x1)) + 1;
1380                        for (; i; i--)
1381                        {
1382                                if (q > 0)
1383                                {
1384                                        xx--;
1385                                        q -= dy;           
1386                                }
1387                                else
1388                                {
1389                                        ut_AddHoriEdgeN(task, xx+1, yy);
1390                                        yy--;
1391                                        q += dx;
1392                                }
1393                        }
1394                }
1395        }
1396}
1397
1398#ifdef _UT_USE_DROPOUT_COLTROL
1399
1400UT_STATIC_API void ut_LineTo_Dropout(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2)
1401{
1402    if ((task->o_cx == o_x2) && (task->o_cy == o_y2))
1403    {
1404        return;
1405    }
1406    if (task->emptyLastPoint)
1407        {
1408                task->emptyLastPoint = 0;
1409                task->o_lx = o_x2;
1410                task->o_ly = o_y2;
1411        }
1412        else
1413        {
1414                ut_CheckLastPoint(task, o_x2, o_y2);
1415        }
1416    task->o_px = task->o_cx;
1417    task->o_py = task->o_cy;
1418    task->o_cx = o_x2;
1419    task->o_cy = o_y2;
1420        if (o_x1 == o_x2)
1421        {
1422                if (o_y1 < o_y2)
1423                {
1424                        int xx = ut_ExceptionAbovePixel(o_x1);
1425                        int yy = ut_AbovePixel(o_y1);
1426                        int ii = ut_BelowPixel(o_y2) - yy + 1;
1427                        for (; ii; ii--)
1428                        {
1429                                ut_AddHoriEdgeP(task, xx, yy);
1430                                yy++;
1431                        }
1432                }
1433                else /*if (o_y1 > o_y2)*/
1434                {
1435                        int xx = ut_AbovePixel(o_x1);
1436                        int yy = ut_BelowPixel(o_y1);
1437                        int ii = yy - ut_AbovePixel(o_y2) + 1;
1438                        for (; ii; ii--)
1439                        {
1440                                ut_AddHoriEdgeN(task, xx, yy);
1441                                yy--;
1442                        }
1443                }
1444        }
1445        else if (o_y1 == o_y2)
1446        {
1447                if (o_x1 < o_x2)
1448                {
1449                        int xx = ut_AbovePixel(o_x1);
1450                        int yy = ut_AbovePixel(o_y1);
1451                        int ii = ut_BelowPixel(o_x2) - xx + 1;
1452                        for (; ii; ii--)
1453                        {
1454                                ut_AddVertEdgeP(task, xx, yy);
1455                                xx++;
1456                        }
1457                }
1458                else /*if (o_x1 > o_x2)*/
1459                {
1460                        int xx = ut_BelowPixel(o_x1);
1461                        int yy = ut_ExceptionAbovePixel(o_y1);
1462                        int ii = xx - ut_AbovePixel(o_x2) + 1;
1463                        for (; ii; ii--)
1464                        {
1465                                ut_AddVertEdgeN(task, xx, yy);
1466                                xx--;
1467                        }
1468                }
1469        }
1470        else if (o_x1 < o_x2)
1471        {
1472                if (o_y1 < o_y2)
1473                {
1474                        int dx = (o_x2-o_x1) << _UT_PIXEL_SHIFT;
1475                        int dy = (o_y2-o_y1) << _UT_PIXEL_SHIFT;
1476                        int xx = ut_AbovePixel(o_x1);
1477                        int yy = ut_AbovePixel(o_y1);
1478                        int ex = ut_BelowPixel(o_x2);
1479                        int ey = ut_BelowPixel(o_y2);
1480                        int ox = ut_AboveScanDelta(o_x1);
1481                        int oy = ut_AboveScanDelta(o_y1);
1482                        int ii = ex - xx + 1 + ey - yy + 1;
1483                        int dd = (o_x2-o_x1)*oy - (o_y2-o_y1)*ox;
1484                        for (; ii; ii--)
1485                        {
1486                                if (dd > 0)
1487                                {
1488                                        ut_AddVertEdgeP(task, xx, yy);
1489                                        xx++;
1490                                        dd -= dy;           
1491                                }
1492                                else
1493                                {
1494                                        ut_AddHoriEdgeP(task, xx, yy);
1495                                        yy++;
1496                                        dd += dx;
1497                                }
1498                        }
1499                }
1500                else /*if (o_y1 > o_y2)*/
1501                {
1502                        int dx = (o_x2-o_x1) << _UT_PIXEL_SHIFT;
1503                        int dy = (o_y1-o_y2) << _UT_PIXEL_SHIFT;
1504                        int xx = ut_AbovePixel(o_x1);
1505                        int yy = ut_BelowPixel(o_y1);
1506                        int ex = ut_BelowPixel(o_x2);
1507                        int ey = ut_AbovePixel(o_y2);
1508                        int ox = ut_AboveScanDelta(o_x1);
1509                        int oy = ut_BelowScanDelta(o_y1);
1510                        int ii = ex - xx + 1 + yy - ey + 1;
1511                        int dd = (o_x2-o_x1)*oy - (o_y1-o_y2)*ox;
1512                        for (; ii; ii--)
1513                        {
1514                                if (dd > 0)
1515                                {
1516                                        ut_AddVertEdgeP(task, xx, yy+1);
1517                                        xx++;
1518                                        dd -= dy;           
1519                                }
1520                                else
1521                                {
1522                                        ut_AddHoriEdgeN(task, xx, yy);
1523                                        yy--;
1524                                        dd += dx;
1525                                }
1526                        }
1527                }
1528        }
1529        else /*if (o_x1 > o_x2)*/
1530        {
1531                if (o_y1 < o_y2)
1532                {
1533                        int dx = (o_x1-o_x2) << _UT_PIXEL_SHIFT;
1534                        int dy = (o_y2-o_y1) << _UT_PIXEL_SHIFT;
1535                        int xx = ut_BelowPixel(o_x1);
1536                        int yy = ut_AbovePixel(o_y1);
1537                        int ex = ut_AbovePixel(o_x2);
1538                        int ey = ut_BelowPixel(o_y2);
1539                        int ox = ut_BelowScanDelta(o_x1);
1540                        int oy = ut_AboveScanDelta(o_y1);
1541                        int ii = xx - ex + 1 + ey - yy + 1;
1542                        int dd = (o_x1-o_x2)*oy - (o_y2-o_y1)*ox;
1543                        for (; ii; ii--)
1544                        {
1545                                if (dd > 0)
1546                                {
1547                                        ut_AddVertEdgeN(task, xx, yy);
1548                                        xx--;
1549                                        dd -= dy;           
1550                                }
1551                                else
1552                                {
1553                                        ut_AddHoriEdgeP(task, xx+1, yy);
1554                                        yy++;
1555                                        dd += dx;
1556                                }
1557                        }
1558                }
1559                else /*if (o_y1 > o_y2)*/
1560                {
1561                        int dx = (o_x1-o_x2) << _UT_PIXEL_SHIFT;
1562                        int dy = (o_y1-o_y2) << _UT_PIXEL_SHIFT;
1563                        int yy = ut_BelowPixel(o_y1);
1564                        int xx = ut_BelowPixel(o_x1);
1565                        int ex = ut_AbovePixel(o_x2);
1566                        int ey = ut_AbovePixel(o_y2);
1567                        int ox = ut_BelowScanDelta(o_x1);
1568                        int oy = ut_BelowScanDelta(o_y1);
1569                        int ii = xx - ex + 1 + yy - ey + 1;
1570                        int dd = (o_x1-o_x2)*oy - (o_y1-o_y2)*ox;
1571                        for (; ii; ii--)
1572                        {
1573                                if (dd > 0)
1574                                {
1575                                        ut_AddVertEdgeN(task, xx, yy+1);
1576                                        xx--;
1577                                        dd -= dy;           
1578                                }
1579                                else
1580                                {
1581                                        ut_AddHoriEdgeN(task, xx + 1, yy);
1582                                        yy--;
1583                                        dd += dx;
1584                                }
1585                        }
1586                }
1587        }
1588}
1589
1590#endif
1591
1592UT_STATIC_API void ut_RegulizeEdge(US_EDGE* scanLine, int nLine)
1593{
1594    US_EDGE* curr;
1595    US_EDGE* from;
1596    int sum;
1597    for (nLine--; nLine>=0; nLine--)
1598    {
1599        for (curr=scanLine[nLine].next; curr; curr=curr->next)
1600        {
1601                        from = curr;
1602                        curr = curr->next;
1603                        if (!curr) break;
1604                        if (from->dir == curr->dir)
1605                        {
1606                                sum = from->dir << 1;
1607                                do
1608                                {
1609                                        curr = curr->next;
1610                                        sum += curr->dir;
1611                                } while (sum);
1612                        }
1613            from->next = curr;
1614        }
1615        for (curr=scanLine[nLine].next; curr;)
1616        {
1617                        if (!curr->next) break;
1618                        if (!curr->next->next) break;
1619                        if (curr->next->pos == curr->next->next->next->pos)
1620                        {
1621                                curr->next = curr->next->next->next;
1622                        }
1623                        else
1624                        {
1625                                curr = curr->next->next;
1626                        }
1627                }
1628    }
1629}
1630
1631UT_STATIC_API void ut_ScanFillMono(UT_FONT_TASK* task)
1632{
1633    int line, s, e;
1634    UT_U32* p;
1635    US_EDGE* edge;
1636#ifdef _UT_USE_DROPOUT_COLTROL
1637        US_EDGE* scanLine;
1638        int nLine;
1639    if (task->isDropout)
1640        {
1641                ut_RegulizeEdge(task->horiScanLine, task->i_ySize);
1642                ut_RegulizeEdge(task->vertScanLine, task->i_xSize);
1643                scanLine = task->horiScanLine;
1644                nLine = task->i_ySize;
1645                for (line=0,p=task->image; line<nLine; line++,p+=task->i_bSize)
1646                {
1647                        for (edge=scanLine[line].next; edge; edge=edge->next->next)
1648                        {
1649                                e = edge->pos;
1650                                s = edge->next->pos;
1651                                if (s<e) ut_FillLineMono(s, e-1+task->emulBold, p);
1652                        }
1653                }
1654                scanLine = task->horiScanLine;
1655                nLine = task->i_ySize;
1656                for (line=0; line<nLine; line++)
1657                {
1658                        for (edge=scanLine[line].next; edge; edge=edge->next->next)
1659                        {
1660                                s = edge->pos;
1661                                if (s!=edge->next->pos) continue;
1662                                if (s > 0) if (ut_GetPixel(task, s-1, line)) continue;
1663                                if (s < task->i_xSize) if (ut_GetPixel(task, s, line)) continue;
1664                                if (s) s--;
1665                                ut_SetPixel(task, s, line);
1666                        }
1667                }
1668        }
1669        else
1670#endif
1671        {
1672                for (line=0,p=task->image; line<task->i_ySize; line++,p+=task->i_bSize)
1673                {
1674                        int sum = 0;
1675                        edge = task->horiScanLine[line].next;
1676                        while (edge)
1677                        {
1678                                if (sum)
1679                                {
1680                                        if (!(sum += edge->dir))
1681                                        {
1682                                                s = edge->pos;
1683                                                if (s<e) ut_FillLineMono(s, e-1+task->emulBold, p);
1684                                        }
1685                                }
1686                                else
1687                                {
1688                                        sum += edge->dir;
1689                                        e = edge->pos;
1690                                }
1691                                edge = edge->next;
1692                        }
1693                }
1694        }
1695}
1696
1697UT_STATIC_API void ut_ScanFillGray(UT_FONT_TASK* task, unsigned char* image)
1698{
1699        int shift = task->grayShift;
1700        int level = 1 << (3-shift);
1701    US_EDGE* edge;
1702    int line, s, e;
1703        for (line=0; line<task->i_ySize; line++)
1704        {
1705                int sum = 0;
1706                edge = task->horiScanLine[line].next;
1707                while (edge)
1708                {
1709                        if (sum)
1710                        {
1711                                if (!(sum += edge->dir))
1712                                {
1713                                        s = edge->pos;
1714                                        if (s<e) ut_FillLineGray(s, e-1+task->emulBold, shift, level, image+(line>>shift)*task->i_bSize);
1715                                }
1716                        }
1717                        else
1718                        {
1719                                sum += edge->dir;
1720                                e = edge->pos;
1721                        }
1722                        edge = edge->next;
1723                }
1724        }
1725}
1726
1727#else /*#ifdef _UT_USE_OLD_SCAN_CONVERSION*/
1728
1729typedef struct US_SPACE
1730{
1731        UT_I16**         left1;
1732        UT_I16**         left2;
1733        UT_I16**         right1;
1734        UT_I16**         right2;
1735} US_SPACE;
1736
1737UT_STATIC_API void ut_AddHoriEdgeP(UT_FONT_TASK* task, int x, int y)
1738{
1739    UT_I16* begin = task->horiSpaceLeft1[y];
1740    UT_I16* end = task->horiSpaceLeft2[y]++;
1741    UT_I16* lead = end - 1;
1742    while ((lead>=begin) && (*lead>x)) *end-- = *lead--;
1743    *end = x;
1744        UT_DEBUG_SCAN_CHECK_BUFFER(task);
1745}
1746
1747UT_STATIC_API void ut_AddHoriEdgeN(UT_FONT_TASK* task, int x, int y)
1748{
1749    UT_I16* begin = task->horiSpaceRight1[y];
1750    UT_I16* end = task->horiSpaceRight2[y]++;
1751    UT_I16* lead = end - 1;
1752    while ((lead>=begin) && (*lead>x)) *end-- = *lead--;
1753    *end = x;
1754        UT_DEBUG_SCAN_CHECK_BUFFER(task);
1755}
1756
1757UT_STATIC_API void ut_AddVertEdgeP(UT_FONT_TASK* task, int x, int y)
1758{
1759    UT_I16* begin = task->vertSpaceLeft1[x];
1760    UT_I16* end = task->vertSpaceLeft2[x]++;
1761    UT_I16* lead = end - 1;
1762    while ((lead>=begin) && (*lead>y)) *end-- = *lead--;
1763    *end = y;
1764        UT_DEBUG_SCAN_CHECK_BUFFER(task);
1765}
1766
1767UT_STATIC_API void ut_AddVertEdgeN(UT_FONT_TASK* task, int x, int y)
1768{
1769    UT_I16* begin = task->vertSpaceRight1[x];
1770    UT_I16* end = task->vertSpaceRight2[x]++;
1771    UT_I16* lead = end - 1;
1772    while ((lead>=begin) && (*lead>y)) *end-- = *lead--;
1773    *end = y;
1774        UT_DEBUG_SCAN_CHECK_BUFFER(task);
1775}
1776
1777UT_STATIC_API void ut_LineTo_Standard(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2)
1778{
1779    if ((task->o_cx == o_x2) && (task->o_cy == o_y2))
1780    {
1781        return;
1782    }
1783    if (task->emptyLastPoint)
1784        {
1785                task->emptyLastPoint = 0;
1786                task->o_lx = o_x2;
1787                task->o_ly = o_y2;
1788        }
1789        else
1790        {
1791                ut_CheckLastPoint(task, o_x2, o_y2);
1792        }
1793    task->o_px = task->o_cx;
1794    task->o_py = task->o_cy;
1795    task->o_cx = o_x2;
1796    task->o_cy = o_y2;
1797        if (o_x1 == o_x2)
1798        {
1799                if (o_y1 < o_y2)
1800                {
1801                        int xx = ut_ExceptionAbovePixel(o_x1);
1802                        int yy = ut_AbovePixel(o_y1);
1803                        int i = ut_BelowPixel(o_y2) - yy + 1;
1804                        for (; i; i--)
1805                        {
1806                                ut_AddHoriEdgeP(task, xx, yy);
1807                                yy++;
1808                        }
1809                }
1810                else /*if (o_y1 > o_y2)*/
1811                {
1812                        int xx = ut_AbovePixel(o_x1);
1813                        int yy = ut_BelowPixel(o_y1);
1814                        int i = yy - ut_AbovePixel(o_y2) + 1;
1815                        for (; i; i--)
1816                        {
1817                                ut_AddHoriEdgeN(task, xx, yy);
1818                                yy--;
1819                        }
1820                }
1821        }
1822        else if (o_x1 < o_x2)
1823        {
1824                if (o_y1 == o_y2)
1825                {
1826                }
1827                else if (o_y1 < o_y2)
1828                {
1829                        int dx = (o_x2-o_x1) << _UT_PIXEL_SHIFT;
1830                        int dy = (o_y2-o_y1) << _UT_PIXEL_SHIFT;
1831                        int xx = ut_AbovePixel(o_x1);
1832                        int yy = ut_AbovePixel(o_y1);
1833                        int i = ut_BelowPixel(o_x2) - xx + 1
1834                                  + ut_BelowPixel(o_y2) - yy + 1;
1835                        int q = ((o_x2-o_x1) * (ut_AboveScanLine(o_y1)-o_y1))
1836                                  - ((o_y2-o_y1) * (ut_AboveScanLine(o_x1)-o_x1));
1837                        for (; i; i--)
1838                        {
1839                                if (q > 0)
1840                                {
1841                                        xx++;
1842                                        q -= dy;           
1843                                }
1844                                else
1845                                {
1846                                        ut_AddHoriEdgeP(task, xx, yy);
1847                                        yy++;
1848                                        q += dx;
1849                                }
1850                        }
1851                }
1852                else /*if (o_y1 > o_y2)*/
1853                {
1854                        int dx = (o_x2-o_x1) << _UT_PIXEL_SHIFT;
1855                        int dy = (o_y1-o_y2) << _UT_PIXEL_SHIFT;
1856                        int xx = ut_AbovePixel(o_x1);
1857                        int yy = ut_BelowPixel(o_y1);
1858                        int i = ut_BelowPixel(o_x2) - xx + 1
1859                                  + yy - ut_AbovePixel(o_y2) + 1;
1860                        int q = ((o_x2-o_x1) * (o_y1-ut_BelowScanLine(o_y1)))
1861                                  - ((o_y1-o_y2) * (ut_AboveScanLine(o_x1)-o_x1)) + 1;
1862                        for (; i; i--)
1863                        {
1864                                if (q > 0)
1865                                {
1866                                        xx++;
1867                                        q -= dy;           
1868                                }
1869                                else
1870                                {
1871                                        ut_AddHoriEdgeN(task, xx, yy);
1872                                        yy--;
1873                                        q += dx;
1874                                }
1875                        }
1876                }
1877        }
1878        else /*if (o_x1 > o_x2)*/
1879        {
1880                if (o_y1 == o_y2)
1881                {
1882                }
1883                else if (o_y1 < o_y2)
1884                {
1885                        int dx = (o_x1-o_x2) << _UT_PIXEL_SHIFT;
1886                        int dy = (o_y2-o_y1) << _UT_PIXEL_SHIFT;
1887                        int xx = ut_BelowPixel(o_x1);
1888                        int yy = ut_AbovePixel(o_y1);
1889                        int i = xx - ut_AbovePixel(o_x2) + 1
1890                                  + ut_BelowPixel(o_y2) - yy + 1;
1891                        int q = ((o_x1-o_x2) * (ut_AboveScanLine(o_y1)-o_y1))
1892                                  - ((o_y2-o_y1) * (o_x1-ut_BelowScanLine(o_x1))) + 1;
1893                        xx++;
1894                        for (; i; i--)
1895                        {
1896                                if (q > 0)
1897                                {
1898                                        xx--;
1899                                        q -= dy;           
1900                                }
1901                                else
1902                                {
1903                                        ut_AddHoriEdgeP(task, xx, yy);
1904                                        yy++;
1905                                        q += dx;
1906                                }
1907                        }
1908                }
1909                else /*if (o_y1 > o_y2)*/
1910                {
1911                        int dx = (o_x1-o_x2) << _UT_PIXEL_SHIFT;
1912                        int dy = (o_y1-o_y2) << _UT_PIXEL_SHIFT;
1913                        int yy = ut_BelowPixel(o_y1);
1914                        int xx = ut_BelowPixel(o_x1);
1915                        int i = yy - ut_AbovePixel(o_y2) + 1
1916                                  + xx - ut_AbovePixel(o_x2) + 1;
1917                        int q = ((o_x1-o_x2) * (o_y1-ut_BelowScanLine(o_y1)))
1918                                  - ((o_y1-o_y2) * (o_x1-ut_BelowScanLine(o_x1))) + 1;
1919                        xx++;
1920                        for (; i; i--)
1921                        {
1922                                if (q > 0)
1923                                {
1924                                        xx--;
1925                                        q -= dy;           
1926                                }
1927                                else
1928                                {
1929                                        ut_AddHoriEdgeN(task, xx, yy);
1930                                        yy--;
1931                                        q += dx;
1932                                }
1933                        }
1934                }
1935        }
1936}
1937
1938#ifdef _UT_USE_DROPOUT_COLTROL
1939
1940UT_STATIC_API void ut_LineTo_Dropout(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2)
1941{
1942    if ((task->o_cx == o_x2) && (task->o_cy == o_y2))
1943    {
1944        return;
1945    }
1946    if (task->emptyLastPoint)
1947        {
1948                task->emptyLastPoint = 0;
1949                task->o_lx = o_x2;
1950                task->o_ly = o_y2;
1951        }
1952        else
1953        {
1954                ut_CheckLastPoint(task, o_x2, o_y2);
1955        }
1956    task->o_px = task->o_cx;
1957    task->o_py = task->o_cy;
1958    task->o_cx = o_x2;
1959    task->o_cy = o_y2;
1960        if (o_x1 == o_x2)
1961        {
1962                if (o_y1 < o_y2)
1963                {
1964                        int xx = ut_ExceptionAbovePixel(o_x1);
1965                        int yy = ut_AbovePixel(o_y1);
1966                        int i = ut_BelowPixel(o_y2) - yy + 1;
1967                        for (; i; i--)
1968                        {
1969                                ut_AddHoriEdgeP(task, xx, yy);
1970                                yy++;
1971                        }
1972                }
1973                else /*if (o_y1 > o_y2)*/
1974                {
1975                        int xx = ut_AbovePixel(o_x1);
1976                        int yy = ut_BelowPixel(o_y1);
1977                        int i = yy - ut_AbovePixel(o_y2) + 1;
1978                        for (; i; i--)
1979                        {
1980                                ut_AddHoriEdgeN(task, xx, yy);
1981                                yy--;
1982                        }
1983                }
1984        }
1985        else if (o_x1 < o_x2)
1986        {
1987                if (o_y1 == o_y2)
1988                {
1989                        int xx = ut_AbovePixel(o_x1);
1990                        int yy = ut_AbovePixel(o_y1);
1991                        int i = ut_BelowPixel(o_x2) - xx + 1;
1992                        for (; i; i--)
1993                        {
1994                                ut_AddVertEdgeP(task, xx, yy);
1995                                xx++;
1996                        }
1997                }
1998                else if (o_y1 < o_y2)
1999                {
2000                        int dx = (o_x2-o_x1) << _UT_PIXEL_SHIFT;
2001                        int dy = (o_y2-o_y1) << _UT_PIXEL_SHIFT;
2002                        int xx = ut_AbovePixel(o_x1);
2003                        int yy = ut_AbovePixel(o_y1);
2004                        int i = ut_BelowPixel(o_x2) - xx + 1
2005                                  + ut_BelowPixel(o_y2) - yy + 1;
2006                        int q = ((o_x2-o_x1) * (ut_AboveScanLine(o_y1)-o_y1))
2007                                  - ((o_y2-o_y1) * (ut_AboveScanLine(o_x1)-o_x1));
2008                        for (; i; i--)
2009                        {
2010                                if (q > 0)
2011                                {
2012                                        ut_AddVertEdgeP(task, xx, yy);
2013                                        xx++;
2014                                        q -= dy;           
2015                                }
2016                                else
2017                                {
2018                                        ut_AddHoriEdgeP(task, xx, yy);
2019                                        yy++;
2020                                        q += dx;
2021                                }
2022                        }
2023                }
2024                else /*if (o_y1 > o_y2)*/
2025                {
2026                        int dx = (o_x2-o_x1) << _UT_PIXEL_SHIFT;
2027                        int dy = (o_y1-o_y2) << _UT_PIXEL_SHIFT;
2028                        int xx = ut_AbovePixel(o_x1);
2029                        int yy = ut_BelowPixel(o_y1);
2030                        int i = ut_BelowPixel(o_x2) - xx + 1
2031                                  + yy - ut_AbovePixel(o_y2) + 1;
2032                        int q = ((o_x2-o_x1) * (o_y1-ut_BelowScanLine(o_y1)))
2033                                  - ((o_y1-o_y2) * (ut_AboveScanLine(o_x1)-o_x1)) + 1;
2034                        for (; i; i--)
2035                        {
2036                                if (q > 0)
2037                                {
2038                                        ut_AddVertEdgeP(task, xx, yy+1);
2039                                        xx++;
2040                                        q -= dy;           
2041                                }
2042                                else
2043                                {
2044                                        ut_AddHoriEdgeN(task, xx, yy);
2045                                        yy--;
2046                                        q += dx;
2047                                }
2048                        }
2049                }
2050        }
2051        else /*if (o_x1 > o_x2)*/
2052        {
2053                if (o_y1 == o_y2)
2054                {
2055                        int xx = ut_BelowPixel(o_x1);
2056                        int yy = ut_ExceptionAbovePixel(o_y1);
2057                        int i = xx - ut_AbovePixel(o_x2) + 1;
2058                        for (; i; i--)
2059                        {
2060                                ut_AddVertEdgeN(task, xx, yy);
2061                                xx--;
2062                        }
2063                }
2064                else if (o_y1 < o_y2)
2065                {
2066                        int dx = (o_x1-o_x2) << _UT_PIXEL_SHIFT;
2067                        int dy = (o_y2-o_y1) << _UT_PIXEL_SHIFT;
2068                        int xx = ut_BelowPixel(o_x1);
2069                        int yy = ut_AbovePixel(o_y1);
2070                        int i = xx - ut_AbovePixel(o_x2) + 1
2071                                  + ut_BelowPixel(o_y2) - yy + 1;
2072                        int q = ((o_x1-o_x2) * (ut_AboveScanLine(o_y1)-o_y1))
2073                                  - ((o_y2-o_y1) * (o_x1-ut_BelowScanLine(o_x1))) + 1;
2074                        for (; i; i--)
2075                        {
2076                                if (q > 0)
2077                                {
2078                                        ut_AddVertEdgeN(task, xx, yy);
2079                                        xx--;
2080                                        q -= dy;           
2081                                }
2082                                else
2083                                {
2084                                        ut_AddHoriEdgeP(task, xx+1, yy);
2085                                        yy++;
2086                                        q += dx;
2087                                }
2088                        }
2089                }
2090                else /*if (o_y1 > o_y2)*/
2091                {
2092                        int dx = (o_x1-o_x2) << _UT_PIXEL_SHIFT;
2093                        int dy = (o_y1-o_y2) << _UT_PIXEL_SHIFT;
2094                        int yy = ut_BelowPixel(o_y1);
2095                        int xx = ut_BelowPixel(o_x1);
2096                        int i = yy - ut_AbovePixel(o_y2) + 1
2097                                  + xx - ut_AbovePixel(o_x2) + 1;
2098                        int q = ((o_x1-o_x2) * (o_y1-ut_BelowScanLine(o_y1)))
2099                                  - ((o_y1-o_y2) * (o_x1-ut_BelowScanLine(o_x1))) + 1;
2100                        for (; i; i--)
2101                        {
2102                                if (q > 0)
2103                                {
2104                                        ut_AddVertEdgeN(task, xx, yy+1);
2105                                        xx--;
2106                                        q -= dy;           
2107                                }
2108                                else
2109                                {
2110                                        ut_AddHoriEdgeN(task, xx + 1, yy);
2111                                        yy--;
2112                                        q += dx;
2113                                }
2114                        }
2115                }
2116        }
2117}
2118
2119#endif
2120
2121UT_STATIC_API void ut_AddExtremePoint(UT_FONT_TASK* task, US_EDGE** rootExtremePoint, UT_COORD o_pos, int dir)
2122{
2123    int pos = (o_pos + _UT_HALF_PIXEL + (dir >> 1)) >> _UT_PIXEL_SHIFT;
2124    while (pos>(*rootExtremePoint)->pos) rootExtremePoint = &((*rootExtremePoint)->next);
2125    task->emptyEdge->pos = pos;
2126    task->emptyEdge->dir = dir;
2127    task->emptyEdge->next = *rootExtremePoint;
2128    *rootExtremePoint = task->emptyEdge++;
2129}
2130
2131UT_STATIC_API int ut_CalcEdgeCount(US_EDGE* rootExtremePoint)
2132{
2133    int total = 0;
2134    while (rootExtremePoint->pos < 0x7fff)
2135    {
2136        if (rootExtremePoint->dir == 1) total += (UT_I32)rootExtremePoint->pos;
2137        else total -= (UT_I32)rootExtremePoint->pos;
2138        rootExtremePoint = rootExtremePoint->next;
2139    }
2140    return total;
2141}
2142
2143UT_STATIC_API void ut_CalcScanBufferSize(UT_FONT_TASK* task)
2144{
2145        #define ScanBufferSize(nLine, nEdge) (nLine)*(sizeof(struct US_SPACE))+(nEdge)*(2*sizeof(UT_I16))
2146    int iPath;
2147    int iPoint;
2148    int iStartPoint, iEndPoint;
2149    int originalPathDir;
2150    int dir, undetermindCount;
2151    UT_COORD prev, next;
2152    UT_COORD* coord;
2153    task->horiScanLine =
2154    task->vertScanLine = (US_EDGE*)&task->rootGlyph.touched[0];
2155    task->horiScanLine->pos = 0x7fff;
2156    task->horiScanLine->dir = 0;
2157    task->horiScanLine->next = 0;
2158    task->emptyEdge = task->horiScanLine + 1;
2159    for (iPath=0; iPath<task->rootGlyph.nPath; iPath++)
2160    {
2161        iStartPoint = task->rootGlyph.startPointIndex[iPath];
2162        iEndPoint   = task->rootGlyph.endPointIndex[iPath];
2163        if (iStartPoint == iEndPoint) continue;
2164        prev = task->rootGlyph.y[iEndPoint];
2165        coord = &task->rootGlyph.y[iStartPoint];
2166        iPoint = iStartPoint;
2167        dir = 0;
2168        undetermindCount = 0;
2169        while ((dir == 0) && (iPoint <= iEndPoint))
2170        {
2171            next = *coord++;
2172            if (next > prev) dir = 1;
2173            else if (next < prev) dir = -1;
2174            else undetermindCount++;
2175            prev = next;
2176            iPoint++;
2177        }
2178        originalPathDir = dir;
2179        while (iPoint <= iEndPoint)
2180        {
2181            next = *coord++;
2182            if (dir == 1)
2183            {
2184                if (next <= prev)
2185                {
2186                    ut_AddExtremePoint(task, &task->horiScanLine, prev, 1);
2187                    dir = -1;
2188                }
2189            }
2190            else
2191            {
2192                if (next >= prev)
2193                {
2194                    ut_AddExtremePoint(task, &task->horiScanLine, prev, -1);
2195                    dir = 1;
2196                }
2197            }
2198            prev = next;
2199            iPoint++;
2200        }
2201        while (undetermindCount > 0)
2202        {
2203            if (!dir)
2204            {
2205                dir = 1;
2206                originalPathDir = 1;
2207            }
2208            ut_AddExtremePoint(task, &task->horiScanLine, prev, dir);
2209            dir = -dir;
2210            undetermindCount--;
2211        }
2212        if (originalPathDir != dir)
2213        {
2214            ut_AddExtremePoint(task, &task->horiScanLine, prev, dir);
2215        }
2216    }
2217    task->horiScanBufferSize = ScanBufferSize(task->i_ySize, ut_CalcEdgeCount(task->horiScanLine));
2218    task->vertScanBufferSize = 0;
2219#ifdef _UT_USE_DROPOUT_COLTROL
2220        if (!task->isDropout) return;
2221    for (iPath=0; iPath<task->rootGlyph.nPath; iPath++)
2222    {
2223        iStartPoint = task->rootGlyph.startPointIndex[iPath];
2224        iEndPoint   = task->rootGlyph.endPointIndex[iPath];
2225        if (iStartPoint == iEndPoint) continue;
2226        prev = task->rootGlyph.x[iEndPoint];
2227        coord = &task->rootGlyph.x[iStartPoint];
2228        iPoint = iStartPoint;
2229        dir = 0;
2230        undetermindCount = 0;
2231        while ((dir == 0) && (iPoint <= iEndPoint))
2232        {
2233            next = *coord++;
2234            if (next > prev) dir = 1;
2235            else if (next < prev) dir = -1;
2236            else undetermindCount++;
2237            prev = next;
2238            iPoint++;
2239        }
2240        originalPathDir = dir;
2241        while (iPoint <= iEndPoint)
2242        {
2243            next = *coord++;
2244            if (dir == 1)
2245            {
2246                if (next <= prev)
2247                {
2248                    ut_AddExtremePoint(task, &task->vertScanLine, prev, 1);
2249                    dir = -1;
2250                }
2251            }
2252            else
2253            {
2254                if (next >= prev)
2255                {
2256                    ut_AddExtremePoint(task, &task->vertScanLine, prev, -1);
2257                    dir = 1;
2258                }
2259            }
2260            prev = next;
2261            iPoint++;
2262        }
2263        while (undetermindCount > 0)
2264        {
2265            if (!dir)
2266            {
2267                dir = 1;
2268                originalPathDir = 1;
2269            }
2270            ut_AddExtremePoint(task, &task->vertScanLine, prev, dir);
2271            dir = -dir;
2272            undetermindCount--;
2273        }
2274        if (originalPathDir != dir)
2275        {
2276            ut_AddExtremePoint(task, &task->vertScanLine, prev, dir);
2277        }
2278    }
2279    task->vertScanBufferSize = ScanBufferSize(task->i_xSize, ut_CalcEdgeCount(task->vertScanLine));
2280#endif
2281        #undef ScanBufferSize
2282}
2283
2284UT_STATIC_API void ut_PrepareScan(UT_FONT_TASK* task)
2285{
2286    int pointerArraySize;
2287    int pos, dir;
2288    US_EDGE* rootExtremePoint;
2289    UT_I16*  edgeCoord;
2290    UT_I16** left1;
2291    UT_I16** left2;
2292    UT_I16** right1;
2293    UT_I16** right2;
2294    char* p = task->edge;
2295    pointerArraySize = task->i_ySize * sizeof(UT_I16*);
2296    task->horiSpaceLeft1 = (UT_I16**)p; p += pointerArraySize;
2297    task->horiSpaceRight1 = (UT_I16**)p; p += pointerArraySize;
2298    task->horiSpaceLeft2 = (UT_I16**)p; p += pointerArraySize;
2299    task->horiSpaceRight2 = (UT_I16**)p; p += pointerArraySize;
2300    edgeCoord = (UT_I16*)p;
2301    rootExtremePoint = task->horiScanLine;
2302    dir = 0;
2303    left1 = task->horiSpaceLeft1;
2304    left2 = task->horiSpaceLeft2;
2305    right1 = task->horiSpaceRight1;
2306    right2 = task->horiSpaceRight2;
2307    for (pos=0; pos<task->i_ySize; pos++)
2308    {
2309        while (rootExtremePoint->pos <= pos)
2310        {
2311            dir -= rootExtremePoint->dir;
2312            rootExtremePoint = rootExtremePoint->next;
2313        }
2314        *left1++  = edgeCoord;
2315        *left2++    = edgeCoord;
2316        edgeCoord  += dir;
2317        *right1++ = edgeCoord;
2318        *right2++   = edgeCoord;
2319        edgeCoord  += dir;
2320    }
2321#ifdef _UT_USE_DROPOUT_COLTROL
2322    if (!task->isDropout) return;
2323    p = task->edge + task->horiScanBufferSize;
2324    pointerArraySize = task->i_xSize * sizeof(UT_I16*);
2325    task->vertSpaceLeft1 = (UT_I16**)p; p += pointerArraySize;
2326    task->vertSpaceRight1 = (UT_I16**)p; p += pointerArraySize;
2327    task->vertSpaceLeft2 = (UT_I16**)p; p += pointerArraySize;
2328    task->vertSpaceRight2 = (UT_I16**)p; p += pointerArraySize;
2329    edgeCoord = (UT_I16*)p;
2330    rootExtremePoint = task->vertScanLine;
2331    dir = 0;
2332    left1 = task->vertSpaceLeft1;
2333    left2 = task->vertSpaceLeft2;
2334    right1 = task->vertSpaceRight1;
2335    right2 = task->vertSpaceRight2;
2336    for (pos=0; pos<task->i_xSize; pos++)
2337    {
2338        while (rootExtremePoint->pos <= pos)
2339        {
2340            dir -= rootExtremePoint->dir;
2341            rootExtremePoint = rootExtremePoint->next;
2342        }
2343        *left1++  = edgeCoord;
2344        *left2++    = edgeCoord;
2345        edgeCoord  += dir;
2346        *right1++ = edgeCoord;
2347        *right2++   = edgeCoord;
2348        edgeCoord  += dir;
2349    }
2350#endif
2351}
2352
2353UT_STATIC_API void ut_ScanFillMono(UT_FONT_TASK* task)
2354{
2355    int line, from, to;
2356    UT_U32* p = task->image;
2357    UT_I16** left1;
2358    UT_I16** left2;
2359    UT_I16** right1;
2360    UT_I16*  on;
2361    UT_I16*  off;
2362    UT_I16*  end;
2363    left1 = task->horiSpaceLeft1;
2364    right1 = task->horiSpaceRight1;
2365    left2 = task->horiSpaceLeft2;
2366    for (line=task->i_ySize; line; line--,p+=task->i_bSize)
2367    {
2368        on  = *left1++;
2369        off = *right1++;
2370        end = *left2++;
2371        while (on < end)
2372        {
2373            from = *on++;
2374            to   = *off++;
2375            if (from < to) ut_FillLineMono(from, to-1+task->emulBold, p);
2376            else if (from > to) ut_FillLineMono(to, from-1+task->emulBold, p);
2377        }
2378    }
2379#ifdef _UT_USE_DROPOUT_COLTROL
2380    if (task->isDropout)
2381        {
2382                int x, y;
2383                UT_I16** right2;
2384                UT_I16*  begin;
2385                left1 = task->horiSpaceLeft1;
2386                left2 = task->horiSpaceLeft2;
2387                right2 = task->horiSpaceRight2;
2388                for (line=0; line<task->i_ySize; line++)
2389                {
2390                        on    = *left2++ - 1;
2391                        off   = *right2++ - 1;
2392                        begin = *left1++;
2393                        for (; on>=begin; on--,off--)
2394                        {
2395                                if (*on == *off)
2396                                {
2397                                        y = line;
2398                                        x = *on;
2399                                        if (x > 0) if (ut_GetPixel(task, x-1, y)) continue;
2400                                        if (x < task->i_xSize) if (ut_GetPixel(task, x, y)) continue;
2401                                        x--;
2402                                        if (x < 0)  x = 0;
2403                                        if (x >= task->i_xSize) x = task->i_xSize - 1;
2404                                        ut_SetPixel(task, x, y);
2405                                }
2406                        }
2407                }
2408                left1 = task->vertSpaceLeft1;
2409                left2 = task->vertSpaceLeft2;
2410                right2 = task->vertSpaceRight2;
2411                for (line=0; line<task->i_xSize; line++)
2412                {
2413                        on    = *left2++ - 1;
2414                        off   = *right2++ - 1;
2415                        begin = *left1++;
2416                        for (; on>=begin; on--,off--)
2417                        {
2418                                if (*on == *off)
2419                                {
2420                                        x = line;
2421                                        y = *on;
2422                                        if (y > 0) if (ut_GetPixel(task, x, y-1)) continue;
2423                                        if (y < task->i_ySize) if (ut_GetPixel(task, x, y)) continue;
2424                                        y--;
2425                                        if (y < 0) y = 0;
2426                                        if (y >= task->i_ySize) y = task->i_ySize - 1;
2427                                        ut_SetPixel(task, x, y);
2428                                }
2429                        }
2430                }
2431        }
2432#endif
2433}
2434
2435UT_STATIC_API void ut_ScanFillGray(UT_FONT_TASK* task, unsigned char* image)
2436{
2437    unsigned char* p = image + task->i_lSize - task->i_bSize;
2438        int shift = task->grayShift;
2439        int level = 1 << (3-shift);
2440    int line, from, to;
2441    UT_I16** left1;
2442    UT_I16** left2;
2443    UT_I16** right1;
2444    UT_I16*  on;
2445    UT_I16*  off;
2446    UT_I16*  end;
2447    left1 = task->horiSpaceLeft1;
2448    right1 = task->horiSpaceRight1;
2449    left2 = task->horiSpaceLeft2;
2450    for (line=task->i_ySize-1; line>=0; line--)
2451    {
2452        on  = *left1++;
2453        off = *right1++;
2454        end = *left2++;
2455        while (on < end)
2456        {
2457            from = *on++;
2458            to   = *off++;
2459            if (from < to) ut_FillLineGray(from, to-1+task->emulBold, shift, level, p-(line>>shift)*task->i_bSize);
2460            else if (from > to) ut_FillLineGray(to, from-1+task->emulBold, shift, level, p-(line>>shift)*task->i_bSize);
2461        }
2462    }
2463}
2464
2465#endif /*#ifdef _UT_USE_OLD_SCAN_CONVERSION*/
2466
2467/***************************************************************************/
2468
2469UT_STATIC_API void ut_PrepareScanGlyph(UT_FC* fc, UT_IMAGE* image)
2470{
2471        UT_FONT_TASK* task = fc->task;
2472        US_RASTER_DIR* xDir = &task->xDir;
2473        US_RASTER_DIR* yDir = &task->yDir;
2474        UT_TRACE1("ut_PrepareScanGlyph()");
2475        UT_TRACE_TAB_INC();
2476    task->isEmpty = 0;
2477        if (task->rootGlyph.nPoint)
2478        {
2479                UT_COORD* x;
2480                UT_COORD* y;
2481                UT_COORD* stop;
2482                int iPath, iStartPoint, iEndPoint;
2483                UT_COORD cx, cy;
2484                UT_COORD o_xMax = task->rootGlyph.x[0];
2485                UT_COORD o_xMin = task->rootGlyph.x[0];
2486#ifdef _UT_REVERSE_OUTLINE_IMAGE
2487                UT_COORD o_yMax = task->emSize - task->rootGlyph.y[0];
2488                UT_COORD o_yMin = task->emSize - task->rootGlyph.y[0];
2489#else
2490                UT_COORD o_yMax = task->rootGlyph.y[0];
2491                UT_COORD o_yMin = task->rootGlyph.y[0];
2492#endif
2493                for (iPath=0; iPath<task->rootGlyph.nPath; iPath++)
2494                {
2495                        iStartPoint = task->rootGlyph.startPointIndex[iPath];
2496                        iEndPoint   = task->rootGlyph.endPointIndex[iPath];
2497                        if (iStartPoint == iEndPoint) continue;
2498                        x = &task->rootGlyph.x[iStartPoint];
2499                        y = &task->rootGlyph.y[iStartPoint];
2500                        stop = &task->rootGlyph.x[iEndPoint];
2501                        while (x <= stop)
2502                        {
2503#ifdef _UT_REVERSE_OUTLINE_IMAGE
2504                                *y = task->emSize - *y;
2505#endif
2506                                cx = *x++;
2507                                cy = *y++;
2508                                if      (o_xMax < cx) o_xMax = cx;
2509                                else if (o_xMin > cx) o_xMin = cx;
2510                                if      (o_yMax < cy) o_yMax = cy;
2511                                else if (o_yMin > cy) o_yMin = cy;
2512                        }
2513                }
2514                if (o_xMin < 0) o_xMin = (o_xMin - _UT_ONE_PIXEL + 1) >> _UT_PIXEL_SHIFT;
2515                else            o_xMin = o_xMin >> _UT_PIXEL_SHIFT;
2516                if (o_yMin < 0) o_yMin = (o_yMin - _UT_ONE_PIXEL + 1) >> _UT_PIXEL_SHIFT;
2517                else            o_yMin = o_yMin >> _UT_PIXEL_SHIFT;
2518                if (o_xMax < 0) o_xMax = (o_xMax - _UT_HALF_PIXEL) >> _UT_PIXEL_SHIFT;
2519                else            o_xMax = (o_xMax + _UT_HALF_PIXEL) >> _UT_PIXEL_SHIFT;
2520                if (o_yMax < 0) o_yMax = (o_yMax - _UT_HALF_PIXEL) >> _UT_PIXEL_SHIFT;
2521                else            o_yMax = (o_yMax + _UT_HALF_PIXEL) >> _UT_PIXEL_SHIFT;
2522        if (o_xMin == o_xMax)
2523        {
2524            o_xMax++;
2525            task->isEmpty = 1;
2526        }
2527        if (o_yMin == o_yMax)
2528        {
2529            o_yMax++;
2530            task->isEmpty = 1;
2531        }
2532        if (o_xMin >= 0)
2533        {
2534            o_xMin = (o_xMin >> task->grayShift) << task->grayShift;
2535        }
2536        else
2537        {
2538            o_xMin = ((o_xMin-xDir->pixelBitCount+1) >> task->grayShift) << task->grayShift;
2539        }
2540        if (o_xMax >= 0)
2541        {
2542            o_xMax = ((o_xMax+xDir->pixelBitCount) >> task->grayShift) << task->grayShift;
2543        }
2544        else
2545        {
2546            o_xMax = ((o_xMax+1) >> task->grayShift) << task->grayShift;
2547        }
2548        if (o_yMin >= 0)
2549        {
2550            o_yMin = (o_yMin >> task->grayShift) << task->grayShift;
2551        }
2552        else
2553        {
2554            o_yMin = ((o_yMin-yDir->pixelBitCount+1) >> task->grayShift) << task->grayShift;
2555        }
2556        if (o_yMax >= 0)
2557        {
2558            o_yMax = ((o_yMax+yDir->pixelBitCount) >> task->grayShift) << task->grayShift;
2559        }
2560        else
2561        {
2562            o_yMax = ((o_yMax+1) >> task->grayShift) << task->grayShift;
2563        }
2564                if (task->emulBold)
2565                {
2566                        task->emulBold = ut_BoldExtra(fc->xSize) << task->grayShift;
2567                        o_xMax += task->emulBold;
2568                }
2569                if (task->emulOutline)
2570                {
2571                        o_xMin -= 1 << task->grayShift;
2572                        o_yMin -= 1 << task->grayShift;
2573                        o_xMax += 1 << task->grayShift;
2574                        o_yMax += 1 << task->grayShift;
2575                }
2576                else if (task->emulEdge)
2577                {
2578                        o_xMin -= ut_GetExtraSizeEdge(task->ySize) << task->grayShift;
2579                        o_yMin -= ut_GetExtraSizeEdge(task->ySize) << task->grayShift;
2580                        o_xMax += ut_GetExtraSizeEdge(task->ySize) << task->grayShift;
2581                        o_yMax += ut_GetExtraSizeEdge(task->ySize) << task->grayShift;
2582                }
2583                if (fc->glyph->cmap->isStroke)
2584                {
2585                        o_xMax += fc->strokeMask.size;
2586                        o_yMax += fc->strokeMask.size;
2587                }
2588                task->i_xMin = o_xMin;
2589                task->i_xMax = o_xMax;
2590                task->i_yMin = o_yMin;
2591                task->i_yMax = o_yMax;
2592                x = &task->rootGlyph.x[0];
2593                y = &task->rootGlyph.y[0];
2594                stop = &task->rootGlyph.x[task->rootGlyph.nPoint];
2595                o_xMin <<= _UT_PIXEL_SHIFT;
2596                o_yMin <<= _UT_PIXEL_SHIFT;
2597                while (x <= stop)
2598                {
2599                        *x++ -= o_xMin;
2600                        *y++ -= o_yMin;
2601                }
2602        }
2603        else
2604        {
2605                task->i_xMin = 0;
2606                task->i_xMax = 0;
2607                task->i_yMin = 0;
2608                task->i_yMax = 0;
2609        }
2610    task->i_ySize = task->i_yMax - task->i_yMin;
2611    task->i_xSize = task->i_xMax - task->i_xMin;
2612        task->i_bSize = (task->i_xSize + 31) >> 5;
2613        task->i_lSize =  task->i_ySize * task->i_bSize;
2614        if (fc->glyph->cmap->isStroke)
2615        {
2616                task->horiScanBufferSize = 0;
2617                task->vertScanBufferSize = 0;
2618        }
2619        else ut_CalcScanBufferSize(task);
2620        if (task->compelPackedImage && (xDir->pixelBitCount == 1) && (yDir->pixelBitCount == 1))
2621    {
2622        image->type = _UT_IMAGE_TYPE_BITMAP;
2623        image->bbox.ox = task->i_xMin;
2624        image->bbox.oy = task->i_yMin;
2625        image->bbox.sx = task->i_xSize;
2626        image->bbox.sy = task->i_ySize;
2627        image->bSize = ut_BSIZE(image->bbox.sx);
2628        image->lSize = image->bSize * image->bbox.sy;
2629    }
2630    else if (task->xDir.subPixelScale)
2631    {
2632        image->type = _UT_IMAGE_TYPE_SUBPIXEL_H;
2633        image->bbox.ox = task->i_xMin  >> task->grayShift;
2634        image->bbox.oy = task->i_yMin  >> task->grayShift;
2635        image->bbox.sx = task->i_xSize >> task->grayShift;
2636        image->bbox.sy = task->i_ySize >> task->grayShift;
2637                image->bSize = ut_BALIGN(image->bbox.sx);
2638        image->lSize = image->bSize * image->bbox.sy;
2639        }
2640    else
2641    {
2642        image->type = _UT_IMAGE_TYPE_BITMAP_65;
2643        image->bbox.ox = task->i_xMin  >> task->grayShift;
2644        image->bbox.oy = task->i_yMin  >> task->grayShift;
2645        image->bbox.sx = task->i_xSize >> task->grayShift;
2646        image->bbox.sy = task->i_ySize >> task->grayShift;
2647                image->bSize = ut_BALIGN(image->bbox.sx);
2648        image->lSize = image->bSize * image->bbox.sy;
2649                if (ut_IsByteImage(fc))
2650                {
2651                        task->i_bSize = image->bSize;
2652                        task->i_lSize = image->lSize;
2653                }
2654    }
2655        UT_TRACE2("task->i_xMin = %d", task->i_xMin);
2656        UT_TRACE2("task->i_xMax = %d", task->i_xMax);
2657        UT_TRACE2("task->i_yMin = %d", task->i_yMin);
2658        UT_TRACE2("task->i_yMax = %d", task->i_yMax);
2659        UT_TRACE2("task->i_ySize = %d", task->i_ySize);
2660        UT_TRACE2("task->i_xSize = %d", task->i_xSize);
2661        UT_TRACE2("task->i_bSize = %d", task->i_bSize);
2662        UT_TRACE2("task->i_lSize = %d", task->i_lSize);
2663        UT_TRACE_TAB_DEC();
2664}
2665
2666UT_STATIC_API void ut_CheckLastPoint(UT_FONT_TASK* task, UT_COORD o_x2, UT_COORD o_y2)
2667{
2668    if (ut_IsOnScanLine(task->o_cy))
2669        {
2670                if (task->o_cy < o_y2)
2671                {
2672                        if (task->o_py > task->o_cy)
2673                                ut_AddHoriEdgeN(task, ut_AbovePixel(task->o_cx), task->o_cy>>_UT_PIXEL_SHIFT);
2674                        if ((task->o_py != task->o_cy) || (task->o_px > task->o_cx))
2675                                ut_AddHoriEdgeP(task, ut_ExceptionAbovePixel(task->o_cx), task->o_cy>>_UT_PIXEL_SHIFT);
2676                }
2677                else if (task->o_cy > o_y2)
2678                {
2679                        if (task->o_py < task->o_cy)
2680                                ut_AddHoriEdgeP(task, ut_ExceptionAbovePixel(task->o_cx), task->o_cy>>_UT_PIXEL_SHIFT);
2681                        if ((task->o_py != task->o_cy) || (task->o_px < task->o_cx))
2682                                ut_AddHoriEdgeN(task, ut_AbovePixel(task->o_cx), task->o_cy>>_UT_PIXEL_SHIFT);
2683                }
2684                else if (task->o_cx < o_x2)
2685                {
2686                        if (task->o_py < task->o_cy)
2687                                ut_AddHoriEdgeP(task, ut_ExceptionAbovePixel(task->o_cx), task->o_cy>>_UT_PIXEL_SHIFT);
2688                        else if ((task->o_py == task->o_cy) && (task->o_px > task->o_cx))
2689                                ut_AddHoriEdgeP(task, ut_ExceptionAbovePixel(task->o_cx), task->o_cy>>_UT_PIXEL_SHIFT);
2690                }
2691                else /*if (task->o_cx > o_x2)*/
2692                {
2693                        if (task->o_py > task->o_cy)
2694                                ut_AddHoriEdgeN(task, ut_AbovePixel(task->o_cx), task->o_cy>>_UT_PIXEL_SHIFT);
2695                        else if ((task->o_py == task->o_cy) && (task->o_px < task->o_cx))
2696                                ut_AddHoriEdgeN(task, ut_AbovePixel(task->o_cx), task->o_cy>>_UT_PIXEL_SHIFT);
2697                }
2698        }
2699#ifdef _UT_USE_DROPOUT_COLTROL
2700    if (!task->isDropout)
2701        {
2702                return;
2703        }
2704    if (ut_IsOnScanLine(task->o_cx))
2705        {
2706                if (task->o_cx < o_x2)
2707                {
2708                        if (task->o_px > task->o_cx)
2709                                ut_AddVertEdgeN(task, task->o_cx>>_UT_PIXEL_SHIFT, ut_ExceptionAbovePixel(task->o_cy));
2710                        if ((task->o_px != task->o_cx) || (task->o_py < task->o_cy))
2711                                ut_AddVertEdgeP(task, task->o_cx>>_UT_PIXEL_SHIFT, ut_AbovePixel(task->o_cy));
2712                }
2713                else if (task->o_cx > o_x2)
2714                {
2715                        if (task->o_px < task->o_cx)
2716                                ut_AddVertEdgeP(task, task->o_cx>>_UT_PIXEL_SHIFT, ut_AbovePixel(task->o_cy));
2717                        if ((task->o_px != task->o_cx) || (task->o_py > task->o_cy))
2718                                ut_AddVertEdgeN(task, task->o_cx>>_UT_PIXEL_SHIFT, ut_ExceptionAbovePixel(task->o_cy));
2719                }
2720                else if (task->o_cy < o_y2)
2721                {
2722                        if (task->o_px > task->o_cx)
2723                                ut_AddVertEdgeN(task, task->o_cx>>_UT_PIXEL_SHIFT, ut_ExceptionAbovePixel(task->o_cy));
2724                        else if ((task->o_px != task->o_cx) && (task->o_py > task->o_cy))
2725                                ut_AddVertEdgeN(task, task->o_cx>>_UT_PIXEL_SHIFT, ut_ExceptionAbovePixel(task->o_cy));
2726                }
2727                else /*if (task->o_cy > o_y2)*/
2728                {
2729                        if (task->o_px < task->o_cx)
2730                                ut_AddVertEdgeP(task, task->o_cx>>_UT_PIXEL_SHIFT, ut_AbovePixel(task->o_cy));
2731                        else if ((task->o_px != task->o_cx) && (task->o_py < task->o_cy))
2732                                ut_AddVertEdgeP(task, task->o_cx>>_UT_PIXEL_SHIFT, ut_AbovePixel(task->o_cy));
2733                }
2734        }
2735#endif
2736}
2737
2738UT_STATIC_API void ut_FillLineMono(int start, int stop, UT_U32* image)
2739{
2740        #define LEFT_MASK(x)    (0xFFFFFFFFU >> (x))
2741        #define RIGHT_MASK(x)   (0xFFFFFFFFU << ((32 - 1) - (x)))
2742    int skip = start >> 5;
2743        UT_TRACE2("ut_FillLineMono() start = %d", start);
2744        UT_TRACE2("                  stop  = %d", stop);
2745        UT_TRACE_TAB_INC();
2746    image += skip;
2747    start  -= skip << 5;
2748    stop   -= skip << 5;
2749    while (stop >= 32)
2750    {
2751        *image |= LEFT_MASK(start);
2752        image++;
2753        start = 0;
2754        stop -= 32;
2755    }
2756    *image |= LEFT_MASK(start) & RIGHT_MASK(stop);
2757        UT_TRACE_TAB_DEC();
2758        #undef LEFT_MASK
2759        #undef RIGHT_MASK
2760}
2761
2762UT_STATIC_API void ut_FillLineGray(int start, int stop, int shift, int level, unsigned char* image)
2763{
2764        for (; start<=stop; start++) image[start>>shift] += level;
2765}
2766
2767UT_STATIC_API void ut_MoveTo(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1)
2768{
2769        UT_TRACE2("ut_MoveTo() o_x1 = %d", o_x1);
2770        UT_TRACE2("            o_y1 = %d", o_y1);
2771        task->emptyLastPoint = 1;
2772    task->o_cx = o_x1;
2773    task->o_cy = o_y1;
2774}
2775
2776#define ut_ClosePath(task) ut_CheckLastPoint(task, task->o_lx, task->o_ly)
2777
2778UT_STATIC_API void ut_BezierSeg(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2, UT_COORD o_x3, UT_COORD o_y3, UT_COORD o_x4, UT_COORD o_y4)
2779{
2780        UT_COORD ox, oy;
2781    UT_COORD o_x23, o_mx, o_x12, o_x1223, o_x2334, o_x34;
2782    UT_COORD o_y23, o_my, o_y12, o_y1223, o_y2334, o_y34;
2783        UT_TRACE2("ut_BezierSeg() o_x1 = %d", o_x1);
2784        UT_TRACE2("            o_y1 = %d", o_y1);
2785        UT_TRACE2("            o_x2 = %d", o_x2);
2786        UT_TRACE2("            o_y2 = %d", o_y2);
2787        UT_TRACE2("            o_x3 = %d", o_x3);
2788        UT_TRACE2("            o_y3 = %d", o_y3);
2789        UT_TRACE2("            o_x4 = %d", o_x4);
2790        UT_TRACE2("            o_y4 = %d", o_y4);
2791        UT_TRACE_TAB_INC();
2792    o_x23 = (o_x2 + o_x3) >> 1;
2793    o_y23 = (o_y2 + o_y3) >> 1;
2794    o_x12 = (o_x1 + o_x2) >> 1;
2795    o_y12 = (o_y1 + o_y2) >> 1;
2796    o_x34 = (o_x3 + o_x4) >> 1;
2797    o_y34 = (o_y3 + o_y4) >> 1;
2798    o_x1223 = (o_x12 + o_x23) >> 1;
2799    o_y1223 = (o_y12 + o_y23) >> 1;
2800    o_x2334 = (o_x34 + o_x23) >> 1;
2801    o_y2334 = (o_y34 + o_y23) >> 1;
2802    o_mx = (o_x1223 + o_x2334) >> 1;
2803    o_my = (o_y1223 + o_y2334) >> 1;
2804    ox = (o_x23 > o_mx) ? (o_x23 - o_mx) : (o_mx - o_x23);
2805    oy = (o_y23 > o_my) ? (o_y23 - o_my) : (o_my - o_y23);
2806        if ((ox > 128) || (oy > 128))
2807    {
2808                ut_BezierSeg(task, o_x1, o_y1, o_x12, o_y12, o_x1223, o_y1223, o_mx, o_my);
2809                ut_BezierSeg(task, o_mx, o_my, o_x2334, o_y2334, o_x34, o_y34, o_x4, o_y4);
2810    }
2811    else
2812    {
2813        task->LineTo(task, o_x1, o_y1, o_x12, o_y12);
2814        task->LineTo(task, o_x12, o_y12, o_x1223, o_y1223);
2815        task->LineTo(task, o_x1223, o_y1223, o_x2334, o_y2334);
2816        task->LineTo(task, o_x2334, o_y2334, o_x34, o_y34);
2817        task->LineTo(task, o_x34, o_y34, o_x4, o_y4);
2818        }
2819        UT_TRACE_TAB_DEC();
2820}
2821
2822UT_STATIC_API void ut_BezierTo(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2, UT_COORD o_x3, UT_COORD o_y3, UT_COORD o_x4, UT_COORD o_y4)
2823{
2824    UT_COORD o_x23, o_mx, o_x12, o_x1223, o_x2334, o_x34;
2825    UT_COORD o_y23, o_my, o_y12, o_y1223, o_y2334, o_y34;
2826        UT_TRACE2("ut_BezierTo() o_x1 = %d", o_x1);
2827        UT_TRACE2("           o_y1 = %d", o_y1);
2828        UT_TRACE2("           o_x2 = %d", o_x2);
2829        UT_TRACE2("           o_y2 = %d", o_y2);
2830        UT_TRACE2("           o_x3 = %d", o_x3);
2831        UT_TRACE2("           o_y3 = %d", o_y3);
2832        UT_TRACE2("           o_x4 = %d", o_x4);
2833        UT_TRACE2("           o_y4 = %d", o_y4);
2834        UT_TRACE_TAB_INC();
2835    o_x23 = (o_x2 + o_x3) >> 1;
2836    o_y23 = (o_y2 + o_y3) >> 1;
2837    o_x12 = (o_x1 + o_x2) >> 1;
2838    o_y12 = (o_y1 + o_y2) >> 1;
2839    o_x34 = (o_x3 + o_x4) >> 1;
2840    o_y34 = (o_y3 + o_y4) >> 1;
2841    o_x1223 = (o_x12 + o_x23) >> 1;
2842    o_y1223 = (o_y12 + o_y23) >> 1;
2843    o_x2334 = (o_x34 + o_x23) >> 1;
2844    o_y2334 = (o_y34 + o_y23) >> 1;
2845    o_mx = (o_x1223 + o_x2334) >> 1;
2846    o_my = (o_y1223 + o_y2334) >> 1;
2847    ut_BezierSeg(task, o_x1, o_y1, o_x12, o_y12, o_x1223, o_y1223, o_mx, o_my);
2848    ut_BezierSeg(task, o_mx, o_my, o_x2334, o_y2334, o_x34, o_y34, o_x4, o_y4);
2849        UT_TRACE_TAB_DEC();
2850}
2851
2852UT_STATIC_API void ut_Spline3To(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2, UT_COORD o_x3, UT_COORD o_y3)
2853{
2854    UT_COORD o_x12 = (o_x1 + o_x2) >> 1;
2855    UT_COORD o_y12 = (o_y1 + o_y2) >> 1;
2856    UT_COORD o_x23 = (o_x2 + o_x3) >> 1;
2857    UT_COORD o_y23 = (o_y2 + o_y3) >> 1;
2858    UT_COORD o_mx  = (o_x12 + o_x23) >> 1;
2859    UT_COORD o_my  = (o_y12 + o_y23) >> 1;
2860        UT_COORD ox = (o_x2 > o_mx) ? (o_x2 - o_mx) : (o_mx - o_x2);
2861        UT_COORD oy = (o_y2 > o_my) ? (o_y2 - o_my) : (o_my - o_y2);
2862        UT_TRACE2("ut_Spline3To() o_x1 = %d", o_x1);
2863        UT_TRACE2("            o_y1 = %d", o_y1);
2864        UT_TRACE2("            o_x2 = %d", o_x2);
2865        UT_TRACE2("            o_y2 = %d", o_y2);
2866        UT_TRACE2("            o_x3 = %d", o_x3);
2867        UT_TRACE2("            o_y3 = %d", o_y3);
2868        UT_TRACE_TAB_INC();
2869        if ((ox > 128) || (oy > 128))
2870    {
2871                ut_Spline3To(task, o_x1, o_y1, o_x12, o_y12, o_mx, o_my);
2872                ut_Spline3To(task, o_mx, o_my, o_x23, o_y23, o_x3, o_y3);
2873    }
2874    else
2875    {
2876        task->LineTo(task, o_x1, o_y1, o_x12, o_y12);
2877        task->LineTo(task, o_x12, o_y12, o_x23, o_y23);
2878        task->LineTo(task, o_x23, o_y23, o_x3, o_y3);
2879        }
2880        UT_TRACE_TAB_DEC();
2881}
2882
2883UT_STATIC_API void ut_Spline4To(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2, UT_COORD o_x3, UT_COORD o_y3, UT_COORD o_x4, UT_COORD o_y4)
2884{
2885    int o_mx = (o_x2 + o_x3) >> 1;
2886    int o_my = (o_y2 + o_y3) >> 1;
2887        UT_TRACE2("ut_Spline4To() o_x1 = %d", o_x1);
2888        UT_TRACE2("            o_y1 = %d", o_y1);
2889        UT_TRACE2("            o_x2 = %d", o_x2);
2890        UT_TRACE2("            o_y2 = %d", o_y2);
2891        UT_TRACE2("            o_x3 = %d", o_x3);
2892        UT_TRACE2("            o_y3 = %d", o_y3);
2893        UT_TRACE2("            o_x4 = %d", o_x4);
2894        UT_TRACE2("            o_y4 = %d", o_y4);
2895        UT_TRACE_TAB_INC();
2896    ut_Spline3To(task, o_x1, o_y1, o_x2, o_y2, o_mx, o_my);
2897    ut_Spline3To(task, o_mx, o_my, o_x3, o_y3, o_x4, o_y4);
2898        UT_TRACE_TAB_DEC();
2899}
2900
2901UT_STATIC_API void ut_LineTo_Stroke(UT_FONT_TASK* task, UT_COORD o_x1, UT_COORD o_y1, UT_COORD o_x2, UT_COORD o_y2)
2902{
2903        UT_TRACE2("ut_LineTo_Stroke() o_x1 = %d", o_x1);
2904        UT_TRACE2("                   o_y1 = %d", o_y1);
2905        UT_TRACE2("                   o_x2 = %d", o_x2);
2906        UT_TRACE2("                   o_y2 = %d", o_y2);
2907        o_x1 = ut_AbovePixel(o_x1);
2908        o_y1 = ut_AbovePixel(o_y1);
2909        o_x2 = ut_AbovePixel(o_x2);
2910        o_y2 = ut_AbovePixel(o_y2);
2911        if (o_x1 == o_x2)
2912        {
2913                UT_COORD i;
2914                if (o_y1 == o_y2) return;
2915                if (o_y1 < o_y2) {for (i=o_y1; i<=o_y2; i++) ut_SetPixel2(task, o_x1, i);}
2916                else             {for (i=o_y2; i<=o_y1; i++) ut_SetPixel2(task, o_x1, i);}
2917                return;
2918        }
2919        if (o_y1 == o_y2)
2920        {
2921                UT_COORD i;
2922                if (o_x1 < o_x2) {for (i=o_x1; i<=o_x2; i++) ut_SetPixel2(task, i, o_y1);}
2923                else             {for (i=o_x2; i<=o_x1; i++) ut_SetPixel2(task, i, o_y1);}
2924                return;
2925        }
2926
2927        {
2928                int x_inc, dx, x = o_x1;
2929                int y_inc, dy, y = o_y1;
2930                if (o_x1 < o_x2)
2931                {
2932                        x_inc = 1;
2933                        dx = o_x2 - o_x1;
2934                }
2935                else
2936                {
2937                        x_inc = -1;
2938                        dx = o_x1 - o_x2;
2939                }
2940                if (o_y1 < o_y2)
2941                {
2942                        y_inc = 1;
2943                        dy = o_y2 - o_y1;
2944                }
2945                else
2946                {
2947                        y_inc = -1;
2948                        dy = o_y1 - o_y2;
2949                }
2950                if (dx >= dy)
2951                {           
2952                        int inc_negative = dy<<1;
2953                        int inc_positive = inc_negative - (dx<<1);
2954                        int sign_checker = inc_negative - dx;
2955                        for (; dx>=0; dx--)
2956                        {
2957                                ut_SetPixel2(task, x, y);
2958                                x += x_inc;
2959                                if (sign_checker > 0)
2960                                {
2961                                        y += y_inc;
2962                                        sign_checker += inc_positive;
2963                                }
2964                                else
2965                                {
2966                                        sign_checker += inc_negative;
2967                                }
2968                        }
2969                }
2970                else
2971                {
2972                        int inc_negative = dx<<1;
2973                        int inc_positive = inc_negative - (dy<<1);
2974                        int sign_checker = inc_negative - dy;
2975                        for (; dy>=0; dy--)
2976                        {
2977                                ut_SetPixel2(task, x, y);
2978                                y += y_inc;
2979                                if (sign_checker > 0)
2980                                {
2981                                        x += x_inc;
2982                                        sign_checker += inc_positive;
2983                                }
2984                                else
2985                                {
2986                                        sign_checker += inc_negative;
2987                                }
2988                        }
2989                }
2990        }
2991}
2992
2993UT_STATIC_API void ut_ScanGlyph(UT_FONT_TASK* task, UT_BOOL mustFill)
2994{
2995        void (*Curve4To)(UT_FONT_TASK*,UT_COORD,UT_COORD,UT_COORD,UT_COORD,UT_COORD,UT_COORD,UT_COORD,UT_COORD) = task->isBezier ? ut_BezierTo : ut_Spline4To;
2996    UT_U16 iPath;
2997    UT_I16 iStartPoint, iEndPoint;
2998    UT_COORD *x;
2999    UT_COORD *y;
3000    UT_U8 *on, oo;
3001    UT_COORD *stop;
3002    UT_COORD x1, x2, x3, x4, mx;
3003    UT_COORD y1, y2, y3, y4, my;
3004        UT_TRACE1("ut_ScanGlyph()");
3005        UT_TRACE_TAB_INC();
3006    if (mustFill)
3007        {
3008                ut_PrepareScan(task);
3009        }
3010    for (iPath=0; iPath<task->rootGlyph.nPath; iPath++)
3011    {
3012        iStartPoint = task->rootGlyph.startPointIndex[iPath];
3013        iEndPoint   = task->rootGlyph.endPointIndex[iPath];
3014        if (iStartPoint == iEndPoint) continue;
3015        x = &task->rootGlyph.x[iStartPoint];
3016        y = &task->rootGlyph.y[iStartPoint];
3017        on = &task->rootGlyph.on[iStartPoint];
3018        stop = &task->rootGlyph.x[iEndPoint];
3019        mx = task->rootGlyph.x[iEndPoint+1];
3020        my = task->rootGlyph.y[iEndPoint+1];
3021        task->rootGlyph.x[iEndPoint+1] = x1 = *x++;
3022        task->rootGlyph.y[iEndPoint+1] = y1 = *y++;
3023        task->rootGlyph.on[iEndPoint+1] = oo = *on++;
3024        if (mustFill && task->rootGlyph.on[iEndPoint]) stop++;
3025        ut_MoveTo(task, x1, y1);
3026        while (x <= stop)
3027        {
3028            if (*on)
3029            {
3030                x2 = *x++;
3031                y2 = *y++;
3032                on++;
3033                task->LineTo(task, x1, y1, x2, y2);
3034                x1 = x2;
3035                y1 = y2;
3036            }
3037            else if (on[1])
3038            {
3039                x2 = *x++;
3040                y2 = *y++;
3041                on++;
3042                x3 = *x++;
3043                y3 = *y++;
3044                on++;
3045                ut_Spline3To(task, x1, y1, x2, y2, x3, y3);
3046                x1 = x3;
3047                y1 = y3;
3048            }
3049            else
3050            {
3051                x2 = *x++;
3052                y2 = *y++;
3053                on++;
3054                x3 = *x++;
3055                y3 = *y++;
3056                on++;
3057                x4 = *x++;
3058                y4 = *y++;
3059                on++;
3060                Curve4To(task, x1, y1, x2, y2, x3, y3, x4, y4);
3061                x1 = x4;
3062                y1 = y4;
3063            }
3064        }
3065                if (mustFill)
3066                {
3067                        ut_ClosePath(task);
3068                }
3069        task->rootGlyph.x[iEndPoint+1] = mx;
3070        task->rootGlyph.y[iEndPoint+1] = my;
3071        task->rootGlyph.on[iEndPoint+1] = oo;
3072    }
3073        UT_TRACE_TAB_DEC();
3074}
3075
3076#if (_UT_CPU_ENDIAN == _UT_LITTLE_ENDIAN)
3077UT_STATIC_API void ut_SwapImage(UT_FONT_TASK* task)
3078{
3079        unsigned char* p = (unsigned char*)task->image;
3080        unsigned char* e = (unsigned char*)(task->image+task->i_lSize);
3081        for (; p<e; p+=4) *((unsigned long*)p) = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
3082}
3083#else
3084#define ut_SwapImage(task)
3085#endif
3086
3087#ifdef _UT_NO_DATA_SEGMENT
3088#define ut_mono2graylevel fontManager->mono2graylevel
3089#define SET_VALUE(index, value) ut_mono2graylevel[index] = value
3090void ut_InitMono2GrayLevel(UT_FONT_MANAGER* fontManager)
3091{
3092#else
3093#define SET_VALUE(index, value) value
3094void ut_InitMono2GrayLevel(UT_FONT_MANAGER* fontManager) {}
3095static char ut_mono2graylevel[] =
3096{
3097#endif
3098        SET_VALUE(  0, 0),
3099        SET_VALUE(  1, 1),
3100        SET_VALUE(  2, 1),
3101        SET_VALUE(  3, 2),
3102        SET_VALUE(  4, 1),
3103        SET_VALUE(  5, 2),
3104        SET_VALUE(  6, 2),
3105        SET_VALUE(  7, 3),
3106        SET_VALUE(  8, 1),
3107        SET_VALUE(  9, 2),
3108        SET_VALUE( 10, 2),
3109        SET_VALUE( 11, 3),
3110        SET_VALUE( 12, 2),
3111        SET_VALUE( 13, 3),
3112        SET_VALUE( 14, 3),
3113        SET_VALUE( 15, 4),
3114        SET_VALUE( 16, 1),
3115        SET_VALUE( 17, 2),
3116        SET_VALUE( 18, 2),
3117        SET_VALUE( 19, 3),
3118        SET_VALUE( 20, 2),
3119        SET_VALUE( 21, 3),
3120        SET_VALUE( 22, 3),
3121        SET_VALUE( 23, 4),
3122        SET_VALUE( 24, 2),
3123        SET_VALUE( 25, 3),
3124        SET_VALUE( 26, 3),
3125        SET_VALUE( 27, 4),
3126        SET_VALUE( 28, 3),
3127        SET_VALUE( 29, 4),
3128        SET_VALUE( 30, 4),
3129        SET_VALUE( 31, 5),
3130        SET_VALUE( 32, 1),
3131        SET_VALUE( 33, 2),
3132        SET_VALUE( 34, 2),
3133        SET_VALUE( 35, 3),
3134        SET_VALUE( 36, 2),
3135        SET_VALUE( 37, 3),
3136        SET_VALUE( 38, 3),
3137        SET_VALUE( 39, 4),
3138        SET_VALUE( 40, 2),
3139        SET_VALUE( 41, 3),
3140        SET_VALUE( 42, 3),
3141        SET_VALUE( 43, 4),
3142        SET_VALUE( 44, 3),
3143        SET_VALUE( 45, 4),
3144        SET_VALUE( 46, 4),
3145        SET_VALUE( 47, 5),
3146        SET_VALUE( 48, 2),
3147        SET_VALUE( 49, 3),
3148        SET_VALUE( 50, 3),
3149        SET_VALUE( 51, 4),
3150        SET_VALUE( 52, 3),
3151        SET_VALUE( 53, 4),
3152        SET_VALUE( 54, 4),
3153        SET_VALUE( 55, 5),
3154        SET_VALUE( 56, 3),
3155        SET_VALUE( 57, 4),
3156        SET_VALUE( 58, 4),
3157        SET_VALUE( 59, 5),
3158        SET_VALUE( 60, 4),
3159        SET_VALUE( 61, 5),
3160        SET_VALUE( 62, 5),
3161        SET_VALUE( 63, 6),
3162        SET_VALUE( 64, 1),
3163        SET_VALUE( 65, 2),
3164        SET_VALUE( 66, 2),
3165        SET_VALUE( 67, 3),
3166        SET_VALUE( 68, 2),
3167        SET_VALUE( 69, 3),
3168        SET_VALUE( 70, 3),
3169        SET_VALUE( 71, 4),
3170        SET_VALUE( 72, 2),
3171        SET_VALUE( 73, 3),
3172        SET_VALUE( 74, 3),
3173        SET_VALUE( 75, 4),
3174        SET_VALUE( 76, 3),
3175        SET_VALUE( 77, 4),
3176        SET_VALUE( 78, 4),
3177        SET_VALUE( 79, 5),
3178        SET_VALUE( 80, 2),
3179        SET_VALUE( 81, 3),
3180        SET_VALUE( 82, 3),
3181        SET_VALUE( 83, 4),
3182        SET_VALUE( 84, 3),
3183        SET_VALUE( 85, 4),
3184        SET_VALUE( 86, 4),
3185        SET_VALUE( 87, 5),
3186        SET_VALUE( 88, 3),
3187        SET_VALUE( 89, 4),
3188        SET_VALUE( 90, 4),
3189        SET_VALUE( 91, 5),
3190        SET_VALUE( 92, 4),
3191        SET_VALUE( 93, 5),
3192        SET_VALUE( 94, 5),
3193        SET_VALUE( 95, 6),
3194        SET_VALUE( 96, 2),
3195        SET_VALUE( 97, 3),
3196        SET_VALUE( 98, 3),
3197        SET_VALUE( 99, 4),
3198        SET_VALUE(100, 3),
3199        SET_VALUE(101, 4),
3200        SET_VALUE(102, 4),
3201        SET_VALUE(103, 5),
3202        SET_VALUE(104, 3),
3203        SET_VALUE(105, 4),
3204        SET_VALUE(106, 4),
3205        SET_VALUE(107, 5),
3206        SET_VALUE(108, 4),
3207        SET_VALUE(109, 5),
3208        SET_VALUE(110, 5),
3209        SET_VALUE(111, 6),
3210        SET_VALUE(112, 3),
3211        SET_VALUE(113, 4),
3212        SET_VALUE(114, 4),
3213        SET_VALUE(115, 5),
3214        SET_VALUE(116, 4),
3215        SET_VALUE(117, 5),
3216        SET_VALUE(118, 5),
3217        SET_VALUE(119, 6),
3218        SET_VALUE(120, 4),
3219        SET_VALUE(121, 5),
3220        SET_VALUE(122, 5),
3221        SET_VALUE(123, 6),
3222        SET_VALUE(124, 5),
3223        SET_VALUE(125, 6),
3224        SET_VALUE(126, 6),
3225        SET_VALUE(127, 7),
3226        SET_VALUE(128, 1),
3227        SET_VALUE(129, 2),
3228        SET_VALUE(130, 2),
3229        SET_VALUE(131, 3),
3230        SET_VALUE(132, 2),
3231        SET_VALUE(133, 3),
3232        SET_VALUE(134, 3),
3233        SET_VALUE(135, 4),
3234        SET_VALUE(136, 2),
3235        SET_VALUE(137, 3),
3236        SET_VALUE(138, 3),
3237        SET_VALUE(139, 4),
3238        SET_VALUE(140, 3),
3239        SET_VALUE(141, 4),
3240        SET_VALUE(142, 4),
3241        SET_VALUE(143, 5),
3242        SET_VALUE(144, 2),
3243        SET_VALUE(145, 3),
3244        SET_VALUE(146, 3),
3245        SET_VALUE(147, 4),
3246        SET_VALUE(148, 3),
3247        SET_VALUE(149, 4),
3248        SET_VALUE(150, 4),
3249        SET_VALUE(151, 5),
3250        SET_VALUE(152, 3),
3251        SET_VALUE(153, 4),
3252        SET_VALUE(154, 4),
3253        SET_VALUE(155, 5),
3254        SET_VALUE(156, 4),
3255        SET_VALUE(157, 5),
3256        SET_VALUE(158, 5),
3257        SET_VALUE(159, 6),
3258        SET_VALUE(160, 2),
3259        SET_VALUE(161, 3),
3260        SET_VALUE(162, 3),
3261        SET_VALUE(163, 4),
3262        SET_VALUE(164, 3),
3263        SET_VALUE(165, 4),
3264        SET_VALUE(166, 4),
3265        SET_VALUE(167, 5),
3266        SET_VALUE(168, 3),
3267        SET_VALUE(169, 4),
3268        SET_VALUE(170, 4),
3269        SET_VALUE(171, 5),
3270        SET_VALUE(172, 4),
3271        SET_VALUE(173, 5),
3272        SET_VALUE(174, 5),
3273        SET_VALUE(175, 6),
3274        SET_VALUE(176, 3),
3275        SET_VALUE(177, 4),
3276        SET_VALUE(178, 4),
3277        SET_VALUE(179, 5),
3278        SET_VALUE(180, 4),
3279        SET_VALUE(181, 5),
3280        SET_VALUE(182, 5),
3281        SET_VALUE(183, 6),
3282        SET_VALUE(184, 4),
3283        SET_VALUE(185, 5),
3284        SET_VALUE(186, 5),
3285        SET_VALUE(187, 6),
3286        SET_VALUE(188, 5),
3287        SET_VALUE(189, 6),
3288        SET_VALUE(190, 6),
3289        SET_VALUE(191, 7),
3290        SET_VALUE(192, 2),
3291        SET_VALUE(193, 3),
3292        SET_VALUE(194, 3),
3293        SET_VALUE(195, 4),
3294        SET_VALUE(196, 3),
3295        SET_VALUE(197, 4),
3296        SET_VALUE(198, 4),
3297        SET_VALUE(199, 5),
3298        SET_VALUE(200, 3),
3299        SET_VALUE(201, 4),
3300        SET_VALUE(202, 4),
3301        SET_VALUE(203, 5),
3302        SET_VALUE(204, 4),
3303        SET_VALUE(205, 5),
3304        SET_VALUE(206, 5),
3305        SET_VALUE(207, 6),
3306        SET_VALUE(208, 3),
3307        SET_VALUE(209, 4),
3308        SET_VALUE(210, 4),
3309        SET_VALUE(211, 5),
3310        SET_VALUE(212, 4),
3311        SET_VALUE(213, 5),
3312        SET_VALUE(214, 5),
3313        SET_VALUE(215, 6),
3314        SET_VALUE(216, 4),
3315        SET_VALUE(217, 5),
3316        SET_VALUE(218, 5),
3317        SET_VALUE(219, 6),
3318        SET_VALUE(220, 5),
3319        SET_VALUE(221, 6),
3320        SET_VALUE(222, 6),
3321        SET_VALUE(223, 7),
3322        SET_VALUE(224, 3),
3323        SET_VALUE(225, 4),
3324        SET_VALUE(226, 4),
3325        SET_VALUE(227, 5),
3326        SET_VALUE(228, 4),
3327        SET_VALUE(229, 5),
3328        SET_VALUE(230, 5),
3329        SET_VALUE(231, 6),
3330        SET_VALUE(232, 4),
3331        SET_VALUE(233, 5),
3332        SET_VALUE(234, 5),
3333        SET_VALUE(235, 6),
3334        SET_VALUE(236, 5),
3335        SET_VALUE(237, 6),
3336        SET_VALUE(238, 6),
3337        SET_VALUE(239, 7),
3338        SET_VALUE(240, 4),
3339        SET_VALUE(241, 5),
3340        SET_VALUE(242, 5),
3341        SET_VALUE(243, 6),
3342        SET_VALUE(244, 5),
3343        SET_VALUE(245, 6),
3344        SET_VALUE(246, 6),
3345        SET_VALUE(247, 7),
3346        SET_VALUE(248, 5),
3347        SET_VALUE(249, 6),
3348        SET_VALUE(250, 6),
3349        SET_VALUE(251, 7),
3350        SET_VALUE(252, 6),
3351        SET_VALUE(253, 7),
3352        SET_VALUE(254, 7),
3353        SET_VALUE(255, 8)
3354#ifdef _UT_NO_DATA_SEGMENT
3355;}
3356#else
3357};
3358#endif
3359#undef SET_VALUE
3360
3361UT_STATIC_API void ut_CompleteImage(UT_FONT_TASK* task, UT_IMAGE* image)
3362{
3363        UT_FONT_MANAGER* fontManager = task->fontManager;
3364    int i_xSize = image->bbox.sx;
3365    int i_ySize = image->bbox.sy;
3366    int d_bSize = image->bSize;
3367    int s_bSize = task->i_bSize << 2;
3368    unsigned char* d = (unsigned char*)image->data;
3369    unsigned char* s = (unsigned char*)task->image;
3370        UT_TRACE2("i_xSize = %d", i_xSize);
3371        UT_TRACE2("i_ySize = %d", i_ySize);
3372        UT_TRACE2("d_bSize = %d", d_bSize);
3373        UT_TRACE2("s_bSize = %d", s_bSize);
3374    switch ((task->xDir.pixelBitCount<<4) | task->yDir.pixelBitCount)
3375    {
3376        case 0x11:
3377        {
3378            if (task->compelPackedImage)
3379            {
3380                                if (d_bSize == s_bSize)
3381                                {
3382                                        image->data = (unsigned char*)task->image;
3383                                }
3384                                else
3385                                {
3386                                        int x, y;
3387                                        for (y=0; y<i_ySize; y++)
3388                                        {
3389                                                for (x=0; x<d_bSize; x++)
3390                                                {
3391                                                        d[x] = s[x];
3392                                                }
3393                                                d += d_bSize;;
3394                                                s += s_bSize;
3395                                        }
3396                                }
3397                                UT_TRACE_TAB_DEC();
3398                                return;
3399            }
3400            else
3401            {
3402                                UT_MEMSET(d, 0, image->lSize);
3403                                ut_Bit2ByteImage(fontManager, s, s_bSize, d, d_bSize, i_xSize, i_ySize, 0, 0);
3404                                break;
3405            }
3406        }
3407        case 0x22:
3408        {
3409            int x, y, l0, l1, l2, l3;
3410            unsigned char *s0, *s1;
3411                    for (y=0; y<i_ySize; y++)
3412                    {
3413                            s0 = s; s += s_bSize;
3414                            s1 = s; s += s_bSize;
3415                            for (x=0; x<d_bSize; x+=4)
3416                            {
3417                                    l0  = ut_mono2graylevel[*s0>>6]; l1  = ut_mono2graylevel[(*s0>>4)&3]; l2  = ut_mono2graylevel[(*s0>>2)&3]; l3  = ut_mono2graylevel[*s0&3]; s0++;
3418                                    l0 += ut_mono2graylevel[*s1>>6]; l1 += ut_mono2graylevel[(*s1>>4)&3]; l2 += ut_mono2graylevel[(*s1>>2)&3]; l3 += ut_mono2graylevel[*s1&3]; s1++;
3419                                    *d++ = l0 << 4;
3420                                    *d++ = l1 << 4;
3421                                    *d++ = l2 << 4;
3422                                    *d++ = l3 << 4;
3423                            }
3424                    }
3425                        break;
3426        }
3427        case 0x44:
3428        {
3429            int x, y, l0, l1;
3430            unsigned char *s0, *s1, *s2, *s3;
3431                    for (y=0; y<i_ySize; y++)
3432                    {
3433                            s0 = s; s += s_bSize;
3434                            s1 = s; s += s_bSize;
3435                            s2 = s; s += s_bSize;
3436                            s3 = s; s += s_bSize;
3437                            for (x=0; x<d_bSize; x+=2)
3438                            {
3439                                    l0  = ut_mono2graylevel[*s0>>4]; l1  = ut_mono2graylevel[*s0&15]; s0++;
3440                                    l0 += ut_mono2graylevel[*s1>>4]; l1 += ut_mono2graylevel[*s1&15]; s1++;
3441                                    l0 += ut_mono2graylevel[*s2>>4]; l1 += ut_mono2graylevel[*s2&15]; s2++;
3442                                    l0 += ut_mono2graylevel[*s3>>4]; l1 += ut_mono2graylevel[*s3&15]; s3++;
3443                                    *d++ = l0 << 2;
3444                                    *d++ = l1 << 2;
3445                            }
3446                    }
3447                        break;
3448        }
3449        case 0x88:
3450        {
3451            int x, y, l;
3452            unsigned char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7;
3453                    for (y=0; y<i_ySize; y++)
3454                    {
3455                            s0 = s; s += s_bSize;
3456                            s1 = s; s += s_bSize;
3457                            s2 = s; s += s_bSize;
3458                            s3 = s; s += s_bSize;
3459                            s4 = s; s += s_bSize;
3460                            s5 = s; s += s_bSize;
3461                            s6 = s; s += s_bSize;
3462                            s7 = s; s += s_bSize;
3463                            for (x=0; x<d_bSize; x++)
3464                            {
3465                                    l  = ut_mono2graylevel[*s0++];
3466                                    l += ut_mono2graylevel[*s1++];
3467                                    l += ut_mono2graylevel[*s2++];
3468                                    l += ut_mono2graylevel[*s3++];
3469                                    l += ut_mono2graylevel[*s4++];
3470                                    l += ut_mono2graylevel[*s5++];
3471                                    l += ut_mono2graylevel[*s6++];
3472                                    l += ut_mono2graylevel[*s7++];
3473                                    *d++ = l;
3474                            }
3475                    }
3476            break;
3477        }
3478                default:
3479                        break;
3480    }
3481}
3482
3483UT_STATIC_API UT_BOOL ut_PrepareOutlineGlyphImage(UT_FC* fc, UT_IMAGE* image)
3484{
3485        UT_FONT_TASK* task = fc->task;
3486        UT_TRACE1("ut_PrepareOutlineGlyphImage()");
3487        UT_TRACE_TAB_INC();
3488        UT_TRACE2("task->compelPackedImage  = %d", task->compelPackedImage);
3489        UT_TRACE2("task->xDir.pixelBitCount = %d", task->xDir.pixelBitCount);
3490        UT_TRACE2("task->yDir.pixelBitCount = %d", task->yDir.pixelBitCount);
3491    if (ut_IsRootGlyphNull(task))
3492    {
3493        image->type = _UT_IMAGE_TYPE_NULL;
3494        image->bbox.ox = 0;
3495        image->bbox.oy = 0;
3496        image->bbox.sx = 0;
3497        image->bbox.sy = 0;
3498        image->bSize = 0;
3499        image->lSize = 0;
3500                UT_TRACE1("image->type = _UT_IMAGE_TYPE_NULL");
3501                UT_TRACE_TAB_DEC();
3502        return _UT_TRUE;
3503    }
3504    if (!task->xDir.pixelBitCount || !task->yDir.pixelBitCount)
3505    {
3506        image->type = _UT_RASTER_TYPE_OUTLINE;
3507                UT_TRACE1("image->type = _UT_RASTER_TYPE_OUTLINE");
3508                UT_TRACE_TAB_DEC();
3509        return _UT_FALSE;
3510    }
3511    ut_PrepareScanGlyph(fc, image);
3512        UT_TRACE_TAB_DEC();
3513    return _UT_TRUE;
3514}
3515
3516UT_STATIC_API void ut_InitStrokeMask(UT_MASK* mask, int size)
3517{
3518        UT_U32* p = mask->bitmap;
3519        if (mask->size == size) return;
3520        mask->size = size;
3521        if (size >= 32)
3522        {
3523                *p++ = 0x0003c000U;
3524                *p++ = 0x003ffc00U;
3525                *p++ = 0x00ffff00U;
3526                *p++ = 0x01ffff80U;
3527                *p++ = 0x07ffffe0U;
3528                *p++ = 0x0ffffff0U;
3529                *p++ = 0x0ffffff0U;
3530                *p++ = 0x1ffffff8U;
3531                *p++ = 0x3ffffffcU;
3532                *p++ = 0x3ffffffcU;
3533                *p++ = 0x7ffffffeU;
3534                *p++ = 0x7ffffffeU;
3535                *p++ = 0x7ffffffeU;
3536                *p++ = 0xffffffffU;
3537                *p++ = 0xffffffffU;
3538                *p++ = 0xffffffffU;
3539                *p++ = 0xffffffffU;
3540                *p++ = 0xffffffffU;
3541                *p++ = 0xffffffffU;
3542                *p++ = 0x7ffffffeU;
3543                *p++ = 0x7ffffffeU;
3544                *p++ = 0x7ffffffeU;
3545                *p++ = 0x3ffffffcU;
3546                *p++ = 0x3ffffffcU;
3547                *p++ = 0x1ffffff8U;
3548                *p++ = 0x0ffffff0U;
3549                *p++ = 0x0ffffff0U;
3550                *p++ = 0x07ffffe0U;
3551                *p++ = 0x01ffff80U;
3552                *p++ = 0x00ffff00U;
3553                *p++ = 0x003ffc00U;
3554                *p++ = 0x0003c000U;
3555        }
3556        else
3557        if (size >= 31)
3558        {
3559                *p++ = 0x0007c000U;
3560                *p++ = 0x007ffc00U;
3561                *p++ = 0x00fffe00U;
3562                *p++ = 0x03ffff80U;
3563                *p++ = 0x07ffffc0U;
3564                *p++ = 0x0fffffe0U;
3565                *p++ = 0x1ffffff0U;
3566                *p++ = 0x1ffffff0U;
3567                *p++ = 0x3ffffff8U;
3568                *p++ = 0x7ffffffcU;
3569                *p++ = 0x7ffffffcU;
3570                *p++ = 0x7ffffffcU;
3571                *p++ = 0x7ffffffcU;
3572                *p++ = 0xfffffffeU;
3573                *p++ = 0xfffffffeU;
3574                *p++ = 0xfffffffeU;
3575                *p++ = 0xfffffffeU;
3576                *p++ = 0xfffffffeU;
3577                *p++ = 0x7ffffffcU;
3578                *p++ = 0x7ffffffcU;
3579                *p++ = 0x7ffffffcU;
3580                *p++ = 0x7ffffffcU;
3581                *p++ = 0x3ffffff8U;
3582                *p++ = 0x1ffffff0U;
3583                *p++ = 0x1ffffff0U;
3584                *p++ = 0x0fffffe0U;
3585                *p++ = 0x07ffffc0U;
3586                *p++ = 0x03ffff80U;
3587                *p++ = 0x00fffe00U;
3588                *p++ = 0x007ffc00U;
3589                *p++ = 0x0007c000U;
3590        }
3591        else
3592        if (size >= 30)
3593        {
3594                *p++ = 0x000fc000U;
3595                *p++ = 0x007ff800U;
3596                *p++ = 0x01fffe00U;
3597                *p++ = 0x03ffff00U;
3598                *p++ = 0x07ffff80U;
3599                *p++ = 0x0fffffc0U;
3600                *p++ = 0x1fffffe0U;
3601                *p++ = 0x3ffffff0U;
3602                *p++ = 0x3ffffff0U;
3603                *p++ = 0x7ffffff8U;
3604                *p++ = 0x7ffffff8U;
3605                *p++ = 0x7ffffff8U;
3606                *p++ = 0xfffffff8U;
3607                *p++ = 0xfffffffcU;
3608                *p++ = 0xfffffffcU;
3609                *p++ = 0xfffffffcU;
3610                *p++ = 0xfffffffcU;
3611                *p++ = 0xfffffff8U;
3612                *p++ = 0x7ffffff8U;
3613                *p++ = 0x7ffffff8U;
3614                *p++ = 0x7ffffff8U;
3615                *p++ = 0x3ffffff0U;
3616                *p++ = 0x3ffffff0U;
3617                *p++ = 0x1fffffe0U;
3618                *p++ = 0x0fffffc0U;
3619                *p++ = 0x07ffff80U;
3620                *p++ = 0x03ffff00U;
3621                *p++ = 0x01fffe00U;
3622                *p++ = 0x007ff800U;
3623                *p++ = 0x000fc000U;
3624        }
3625        else
3626        if (size >= 29)
3627        {
3628                *p++ = 0x000f8000U;
3629                *p++ = 0x007ff800U;
3630                *p++ = 0x01fffc00U;
3631                *p++ = 0x03ffff00U;
3632                *p++ = 0x0fffff80U;
3633                *p++ = 0x0fffffc0U;
3634                *p++ = 0x1fffffc0U;
3635                *p++ = 0x3fffffe0U;
3636                *p++ = 0x3ffffff0U;
3637                *p++ = 0x7ffffff0U;
3638                *p++ = 0x7ffffff0U;
3639                *p++ = 0x7ffffff0U;
3640                *p++ = 0xfffffff8U;
3641                *p++ = 0xfffffff8U;
3642                *p++ = 0xfffffff8U;
3643                *p++ = 0xfffffff8U;
3644                *p++ = 0xfffffff8U;
3645                *p++ = 0x7ffffff0U;
3646                *p++ = 0x7ffffff0U;
3647                *p++ = 0x7ffffff0U;
3648                *p++ = 0x3ffffff0U;
3649                *p++ = 0x3fffffe0U;
3650                *p++ = 0x1fffffc0U;
3651                *p++ = 0x0fffffc0U;
3652                *p++ = 0x0fffff80U;
3653                *p++ = 0x03fffe00U;
3654                *p++ = 0x01fffc00U;
3655                *p++ = 0x007ff000U;
3656                *p++ = 0x000f8000U;
3657        }
3658        else
3659        if (size >= 28)
3660        {
3661                *p++ = 0x000f0000U;
3662                *p++ = 0x00fff000U;
3663                *p++ = 0x01fff800U;
3664                *p++ = 0x07fffe00U;
3665                *p++ = 0x0fffff00U;
3666                *p++ = 0x1fffff80U;
3667                *p++ = 0x1fffff80U;
3668                *p++ = 0x3fffffc0U;
3669                *p++ = 0x7fffffe0U;
3670                *p++ = 0x7fffffe0U;
3671                *p++ = 0x7fffffe0U;
3672                *p++ = 0x7fffffe0U;
3673                *p++ = 0xfffffff0U;
3674                *p++ = 0xfffffff0U;
3675                *p++ = 0xfffffff0U;
3676                *p++ = 0xfffffff0U;
3677                *p++ = 0x7fffffe0U;
3678                *p++ = 0x7fffffe0U;
3679                *p++ = 0x7fffffe0U;
3680                *p++ = 0x7fffffe0U;
3681                *p++ = 0x3fffffc0U;
3682                *p++ = 0x1fffff80U;
3683                *p++ = 0x1fffff80U;
3684                *p++ = 0x0fffff00U;
3685                *p++ = 0x07fffe00U;
3686                *p++ = 0x01fff800U;
3687                *p++ = 0x00fff000U;
3688                *p++ = 0x000f0000U;
3689        }
3690        else
3691        if (size >= 27)
3692        {
3693                *p++ = 0x001f0000U;
3694                *p++ = 0x00ffe000U;
3695                *p++ = 0x03fff800U;
3696                *p++ = 0x07fffc00U;
3697                *p++ = 0x0ffffe00U;
3698                *p++ = 0x1fffff00U;
3699                *p++ = 0x3fffff80U;
3700                *p++ = 0x3fffff80U;
3701                *p++ = 0x7fffffc0U;
3702                *p++ = 0x7fffffc0U;
3703                *p++ = 0x7fffffc0U;
3704                *p++ = 0xffffffe0U;
3705                *p++ = 0xffffffe0U;
3706                *p++ = 0xffffffe0U;
3707                *p++ = 0xffffffe0U;
3708                *p++ = 0xffffffe0U;
3709                *p++ = 0x7fffffc0U;
3710                *p++ = 0x7fffffc0U;
3711                *p++ = 0x7fffffc0U;
3712                *p++ = 0x3fffff80U;
3713                *p++ = 0x3fffff80U;
3714                *p++ = 0x1fffff00U;
3715                *p++ = 0x0ffffe00U;
3716                *p++ = 0x07fffc00U;
3717                *p++ = 0x03fff800U;
3718                *p++ = 0x00ffe000U;
3719                *p++ = 0x001f0000U;
3720        }
3721        else
3722        if (size >= 26)
3723        {
3724                *p++ = 0x001e0000U;
3725                *p++ = 0x01ffe000U;
3726                *p++ = 0x03fff000U;
3727                *p++ = 0x0ffffc00U;
3728                *p++ = 0x1ffffe00U;
3729                *p++ = 0x1ffffe00U;
3730                *p++ = 0x3fffff00U;
3731                *p++ = 0x7fffff80U;
3732                *p++ = 0x7fffff80U;
3733                *p++ = 0x7fffff80U;
3734                *p++ = 0x7fffff80U;
3735                *p++ = 0xffffffc0U;
3736                *p++ = 0xffffffc0U;
3737                *p++ = 0xffffffc0U;
3738                *p++ = 0xffffffc0U;
3739                *p++ = 0x7fffff80U;
3740                *p++ = 0x7fffff80U;
3741                *p++ = 0x7fffff80U;
3742                *p++ = 0x7fffff80U;
3743                *p++ = 0x3fffff00U;
3744                *p++ = 0x1ffffe00U;
3745                *p++ = 0x1ffffe00U;
3746                *p++ = 0x0ffffc00U;
3747                *p++ = 0x03fff000U;
3748                *p++ = 0x01ffe000U;
3749                *p++ = 0x001e0000U;
3750        }
3751        else
3752        if (size >= 25)
3753        {
3754                *p++ = 0x003e0000U;
3755                *p++ = 0x01ffc000U;
3756                *p++ = 0x07fff000U;
3757                *p++ = 0x0ffff800U;
3758                *p++ = 0x1ffffc00U;
3759                *p++ = 0x3ffffe00U;
3760                *p++ = 0x3ffffe00U;
3761                *p++ = 0x7fffff00U;
3762                *p++ = 0x7fffff00U;
3763                *p++ = 0x7fffff00U;
3764                *p++ = 0xffffff80U;
3765                *p++ = 0xffffff80U;
3766                *p++ = 0xffffff80U;
3767                *p++ = 0xffffff80U;
3768                *p++ = 0xffffff80U;
3769                *p++ = 0x7fffff00U;
3770                *p++ = 0x7fffff00U;
3771                *p++ = 0x7fffff00U;
3772                *p++ = 0x3ffffe00U;
3773                *p++ = 0x3ffffe00U;
3774                *p++ = 0x1ffffc00U;
3775                *p++ = 0x0ffff800U;
3776                *p++ = 0x07fff000U;
3777                *p++ = 0x01ffc000U;
3778                *p++ = 0x003e0000U;
3779        }
3780        else
3781        if (size >= 24)
3782        {
3783                *p++ = 0x003c0000U;
3784                *p++ = 0x01ff8000U;
3785                *p++ = 0x07ffe000U;
3786                *p++ = 0x0ffff000U;
3787                *p++ = 0x1ffff800U;
3788                *p++ = 0x3ffffc00U;
3789                *p++ = 0x3ffffc00U;
3790                *p++ = 0x7ffffe00U;
3791                *p++ = 0x7ffffe00U;
3792                *p++ = 0xffffff00U;
3793                *p++ = 0xffffff00U;
3794                *p++ = 0xffffff00U;
3795                *p++ = 0xffffff00U;
3796                *p++ = 0xffffff00U;
3797                *p++ = 0xffffff00U;
3798                *p++ = 0x7ffffe00U;
3799                *p++ = 0x7ffffe00U;
3800                *p++ = 0x3ffffc00U;
3801                *p++ = 0x3ffffc00U;
3802                *p++ = 0x1ffff800U;
3803                *p++ = 0x0ffff000U;
3804                *p++ = 0x07ffe000U;
3805                *p++ = 0x01ff8000U;
3806                *p++ = 0x003c0000U;
3807        }
3808        else
3809        if (size >= 23)
3810        {
3811                *p++ = 0x007c0000U;
3812                *p++ = 0x03ff8000U;
3813                *p++ = 0x07ffc000U;
3814                *p++ = 0x1ffff000U;
3815                *p++ = 0x1ffff000U;
3816                *p++ = 0x3ffff800U;
3817                *p++ = 0x7ffffc00U;
3818                *p++ = 0x7ffffc00U;
3819                *p++ = 0x7ffffc00U;
3820                *p++ = 0xfffffe00U;
3821                *p++ = 0xfffffe00U;
3822                *p++ = 0xfffffe00U;
3823                *p++ = 0xfffffe00U;
3824                *p++ = 0xfffffe00U;
3825                *p++ = 0x7ffffc00U;
3826                *p++ = 0x7ffffc00U;
3827                *p++ = 0x7ffffc00U;
3828                *p++ = 0x3ffff800U;
3829                *p++ = 0x1ffff000U;
3830                *p++ = 0x1ffff000U;
3831                *p++ = 0x07ffc000U;
3832                *p++ = 0x03ff8000U;
3833                *p++ = 0x007c0000U;
3834        }
3835        else
3836        if (size >= 22)
3837        {
3838                *p++ = 0x00fc0000U;
3839                *p++ = 0x03ff0000U;
3840                *p++ = 0x0fffc000U;
3841                *p++ = 0x1fffe000U;
3842                *p++ = 0x3ffff000U;
3843                *p++ = 0x3ffff000U;
3844                *p++ = 0x7ffff800U;
3845                *p++ = 0x7ffff800U;
3846                *p++ = 0xfffff800U;
3847                *p++ = 0xfffffc00U;
3848                *p++ = 0xfffffc00U;
3849                *p++ = 0xfffffc00U;
3850                *p++ = 0xfffffc00U;
3851                *p++ = 0xfffff800U;
3852                *p++ = 0x7ffff800U;
3853                *p++ = 0x7ffff800U;
3854                *p++ = 0x3ffff000U;
3855                *p++ = 0x3ffff000U;
3856                *p++ = 0x1fffe000U;
3857                *p++ = 0x0fffc000U;
3858                *p++ = 0x03ff0000U;
3859                *p++ = 0x00780000U;
3860        }
3861        else
3862        if (size >= 21)
3863        {
3864                *p++ = 0x00f80000U;
3865                *p++ = 0x03fe0000U;
3866                *p++ = 0x0fff8000U;
3867                *p++ = 0x1fffc000U;
3868                *p++ = 0x3fffe000U;
3869                *p++ = 0x3fffe000U;
3870                *p++ = 0x7ffff000U;
3871                *p++ = 0x7ffff000U;
3872                *p++ = 0xfffff800U;
3873                *p++ = 0xfffff800U;
3874                *p++ = 0xfffff800U;
3875                *p++ = 0xfffff800U;
3876                *p++ = 0xfffff800U;
3877                *p++ = 0x7ffff000U;
3878                *p++ = 0x7ffff000U;
3879                *p++ = 0x3fffe000U;
3880                *p++ = 0x3fffe000U;
3881                *p++ = 0x1fffc000U;
3882                *p++ = 0x0fff8000U;
3883                *p++ = 0x03fe0000U;
3884                *p++ = 0x00f80000U;
3885        }
3886        else
3887        if (size >= 20)
3888        {
3889                *p++ = 0x00f00000U;
3890                *p++ = 0x07fe0000U;
3891                *p++ = 0x0fff0000U;
3892                *p++ = 0x1fff8000U;
3893                *p++ = 0x3fffc000U;
3894                *p++ = 0x7fffe000U;
3895                *p++ = 0x7fffe000U;
3896                *p++ = 0x7fffe000U;
3897                *p++ = 0xfffff000U;
3898                *p++ = 0xfffff000U;
3899                *p++ = 0xfffff000U;
3900                *p++ = 0xfffff000U;
3901                *p++ = 0x7fffe000U;
3902                *p++ = 0x7fffe000U;
3903                *p++ = 0x7fffe000U;
3904                *p++ = 0x3fffc000U;
3905                *p++ = 0x1fff8000U;
3906                *p++ = 0x0fff0000U;
3907                *p++ = 0x07fe0000U;
3908                *p++ = 0x00f00000U;
3909        }
3910        else
3911        if (size >= 19)
3912        {
3913                *p++ = 0x01f00000U;
3914                *p++ = 0x07fc0000U;
3915                *p++ = 0x1fff0000U;
3916                *p++ = 0x3fff8000U;
3917                *p++ = 0x3fff8000U;
3918                *p++ = 0x7fffc000U;
3919                *p++ = 0x7fffc000U;
3920                *p++ = 0xffffe000U;
3921                *p++ = 0xffffe000U;
3922                *p++ = 0xffffe000U;
3923                *p++ = 0xffffe000U;
3924                *p++ = 0xffffe000U;
3925                *p++ = 0x7fffc000U;
3926                *p++ = 0x7fffc000U;
3927                *p++ = 0x3fff8000U;
3928                *p++ = 0x3fff8000U;
3929                *p++ = 0x1fff0000U;
3930                *p++ = 0x07fc0000U;
3931                *p++ = 0x01f00000U;
3932        }
3933        else
3934        if (size >= 18)
3935        {
3936                *p++ = 0x01e00000U;
3937                *p++ = 0x0ffc0000U;
3938                *p++ = 0x1ffe0000U;
3939                *p++ = 0x3fff0000U;
3940                *p++ = 0x7fff8000U;
3941                *p++ = 0x7fff8000U;
3942                *p++ = 0x7fff8000U;
3943                *p++ = 0xffffc000U;
3944                *p++ = 0xffffc000U;
3945                *p++ = 0xffffc000U;
3946                *p++ = 0xffffc000U;
3947                *p++ = 0x7fff8000U;
3948                *p++ = 0x7fff8000U;
3949                *p++ = 0x7fff8000U;
3950                *p++ = 0x3fff0000U;
3951                *p++ = 0x1ffe0000U;
3952                *p++ = 0x0ffc0000U;
3953                *p++ = 0x01e00000U;
3954        }
3955        else
3956        if (size >= 17)
3957        {
3958                *p++ = 0x03e00000U;
3959                *p++ = 0x0ff80000U;
3960                *p++ = 0x1ffc0000U;
3961                *p++ = 0x3ffe0000U;
3962                *p++ = 0x7fff0000U;
3963                *p++ = 0x7fff0000U;
3964                *p++ = 0xffff8000U;
3965                *p++ = 0xffff8000U;
3966                *p++ = 0xffff8000U;
3967                *p++ = 0xffff8000U;
3968                *p++ = 0xffff8000U;
3969                *p++ = 0x7fff0000U;
3970                *p++ = 0x7fff0000U;
3971                *p++ = 0x3ffe0000U;
3972                *p++ = 0x1ffc0000U;
3973                *p++ = 0x0ff80000U;
3974                *p++ = 0x03e00000U;
3975        }
3976        else
3977        if (size >= 16)
3978        {
3979                *p++ = 0x07e00000U;
3980                *p++ = 0x0ff00000U;
3981                *p++ = 0x3ffc0000U;
3982                *p++ = 0x3ffc0000U;
3983                *p++ = 0x7ffe0000U;
3984                *p++ = 0xffff0000U;
3985                *p++ = 0xffff0000U;
3986                *p++ = 0xffff0000U;
3987                *p++ = 0xffff0000U;
3988                *p++ = 0xffff0000U;
3989                *p++ = 0xffff0000U;
3990                *p++ = 0x7ffe0000U;
3991                *p++ = 0x3ffc0000U;
3992                *p++ = 0x3ffc0000U;
3993                *p++ = 0x0ff00000U;
3994                *p++ = 0x07e00000U;
3995        }
3996        else
3997        if (size >= 15)
3998        {
3999                *p++ = 0x07c00000U;
4000                *p++ = 0x1ff00000U;
4001                *p++ = 0x3ff80000U;
4002                *p++ = 0x7ffc0000U;
4003                *p++ = 0x7ffc0000U;
4004                *p++ = 0xfffe0000U;
4005                *p++ = 0xfffe0000U;
4006                *p++ = 0xfffe0000U;
4007                *p++ = 0xfffe0000U;
4008                *p++ = 0xfffe0000U;
4009                *p++ = 0x7ffc0000U;
4010                *p++ = 0x7ffc0000U;
4011                *p++ = 0x3ff80000U;
4012                *p++ = 0x1ff00000U;
4013                *p++ = 0x07c00000U;
4014        }
4015        else
4016        if (size >= 14)
4017        {
4018                *p++ = 0x0fc00000U;
4019                *p++ = 0x1fe00000U;
4020                *p++ = 0x3ff00000U;
4021                *p++ = 0x7ff80000U;
4022                *p++ = 0xfff80000U;
4023                *p++ = 0xfffc0000U;
4024                *p++ = 0xfffc0000U;
4025                *p++ = 0xfffc0000U;
4026                *p++ = 0xfffc0000U;
4027                *p++ = 0xfff80000U;
4028                *p++ = 0x7ff80000U;
4029                *p++ = 0x3ff00000U;
4030                *p++ = 0x1fe00000U;
4031                *p++ = 0x0fc00000U;
4032        }
4033        else
4034        if (size >= 13)
4035        {
4036                *p++ = 0x0f800000U;
4037                *p++ = 0x1fc00000U;
4038                *p++ = 0x3fe00000U;
4039                *p++ = 0x7ff00000U;
4040                *p++ = 0x7ff00000U;
4041                *p++ = 0xfff80000U;
4042                *p++ = 0xfff80000U;
4043                *p++ = 0xfff80000U;
4044                *p++ = 0x7ff00000U;
4045                *p++ = 0x7ff00000U;
4046                *p++ = 0x3fe00000U;
4047                *p++ = 0x1fc00000U;
4048                *p++ = 0x0f800000U;
4049        }
4050        else
4051        if (size >= 12)
4052        {
4053                *p++ = 0x06000000U;
4054                *p++ = 0x3fc00000U;
4055                *p++ = 0x7fe00000U;
4056                *p++ = 0x7fe00000U;
4057                *p++ = 0x7fe00000U;
4058                *p++ = 0xfff00000U;
4059                *p++ = 0xfff00000U;
4060                *p++ = 0x7fe00000U;
4061                *p++ = 0x7fe00000U;
4062                *p++ = 0x7fe00000U;
4063                *p++ = 0x3fc00000U;
4064                *p++ = 0x06000000U;
4065        }
4066        else
4067        if (size >= 11)
4068        {
4069                *p++ = 0x0e000000U;
4070                *p++ = 0x3f800000U;
4071                *p++ = 0x7fc00000U;
4072                *p++ = 0x7fc00000U;
4073                *p++ = 0xffe00000U;
4074                *p++ = 0xffe00000U;
4075                *p++ = 0xffe00000U;
4076                *p++ = 0x7fc00000U;
4077                *p++ = 0x7fc00000U;
4078                *p++ = 0x3f800000U;
4079                *p++ = 0x0e000000U;
4080        }
4081        else
4082        if (size >= 10)
4083        {
4084                *p++ = 0x0c000000U;
4085                *p++ = 0x3f000000U;
4086                *p++ = 0x7f800000U;
4087                *p++ = 0x7f800000U;
4088                *p++ = 0xffc00000U;
4089                *p++ = 0xffc00000U;
4090                *p++ = 0x7f800000U;
4091                *p++ = 0x7f800000U;
4092                *p++ = 0x3f000000U;
4093                *p++ = 0x0c000000U;
4094        }
4095        else
4096        if (size >= 9)
4097        {
4098                *p++ = 0x1c000000U;
4099                *p++ = 0x7f000000U;
4100                *p++ = 0x7f000000U;
4101                *p++ = 0xff800000U;
4102                *p++ = 0xff800000U;
4103                *p++ = 0xff800000U;
4104                *p++ = 0x7f000000U;
4105                *p++ = 0x7f000000U;
4106                *p++ = 0x1c000000U;
4107        }
4108        else
4109        if (size >= 8)
4110        {
4111                *p++ = 0x18000000U;
4112                *p++ = 0x7e000000U;
4113                *p++ = 0x7e000000U;
4114                *p++ = 0xff000000U;
4115                *p++ = 0xff000000U;
4116                *p++ = 0x7e000000U;
4117                *p++ = 0x7e000000U;
4118                *p++ = 0x18000000U;
4119        }
4120        else
4121        if (size >= 7)
4122        {
4123                *p++ = 0x38000000U;
4124                *p++ = 0x7c000000U;
4125                *p++ = 0xfe000000U;
4126                *p++ = 0xfe000000U;
4127                *p++ = 0xfe000000U;
4128                *p++ = 0x7c000000U;
4129                *p++ = 0x38000000U;
4130        }
4131        else
4132        if (size >= 6)
4133        {
4134                *p++ = 0x30000000U;
4135                *p++ = 0x78000000U;
4136                *p++ = 0xfc000000U;
4137                *p++ = 0xfc000000U;
4138                *p++ = 0x78000000U;
4139                *p++ = 0x30000000U;
4140        }
4141        else
4142        if (size >= 5)
4143        {
4144                *p++ = 0x70000000U;
4145                *p++ = 0xf8000000U;
4146                *p++ = 0xf8000000U;
4147                *p++ = 0xf8000000U;
4148                *p++ = 0x70000000U;
4149        }
4150        else
4151        if (size >= 4)
4152        {
4153                *p++ = 0x60000000U;
4154                *p++ = 0xf0000000U;
4155                *p++ = 0xf0000000U;
4156                *p++ = 0x60000000U;
4157        }
4158        else
4159        if (size >= 3)
4160        {
4161                *p++ = 0x40000000U;
4162                *p++ = 0xe0000000U;
4163                *p++ = 0x40000000U;
4164        }
4165        else
4166        if (size >= 2)
4167        {
4168                *p++ = 0xc0000000U;
4169                *p++ = 0xc0000000U;
4170        }
4171        else
4172        {
4173                *p++ = 0x10000000U;
4174        }
4175}
4176
4177UT_STATIC_API UT_BOOL ut_PrepareRasterGlyphOutline(UT_FC* fc, UT_IMAGE* image)
4178{
4179        /*                                              OL  G65  G17  G5  G2  B2*/
4180    char pixelBitCount[] = { 0,   8,   4,  2,  1,  1};
4181    char grayFullShift[] = { 0,   3,   2,  1,  0,  0};
4182    char grayPreShift[]  = { 0,   3,   2,  1,  0,  0};
4183    char compelPack[]    = { 0,   0,   0,  0,  0,  1};
4184        UT_FONT_TASK* task = fc->task;
4185        US_RASTER_DIR* xDir = &task->xDir;
4186        US_RASTER_DIR* yDir = &task->yDir;
4187        int rasterType = fc->rasterType;
4188        int xGrayType = fc->xGrayType;
4189        int yGrayType = fc->yGrayType;
4190        UT_BOOL result;
4191        if (fc->glyph->cmap->isStroke)
4192        {
4193                rasterType = _UT_RASTER_TYPE_GRAY_5;
4194                xGrayType = 0;
4195                yGrayType = 0;
4196        }
4197        UT_TRACE1("ut_PrepareRasterGlyphOutline()");
4198        UT_TRACE_TAB_INC();
4199    task->xSize = fc->xSize;
4200    task->ySize = fc->ySize;
4201        task->grayShift = grayFullShift[rasterType+1];
4202        xDir->gridFitSize = fc->xSize;
4203        yDir->gridFitSize = fc->ySize;
4204        xDir->subPixelScale = 0;
4205        yDir->subPixelScale = 0;
4206        if (task->emulOutline) task->emulEdge = 0;
4207        if (!task->grayShift)
4208        {
4209                xDir->pixelBitCount = 1;
4210                yDir->pixelBitCount = 1;
4211                task->grayShift = 0;
4212                task->grayShift = 0;
4213                xDir->grayPreShift  = 0;
4214                yDir->grayPreShift  = 0;
4215                xDir->grayPostShift = 0;
4216                yDir->grayPostShift = 0;
4217                xDir->isGray = 0;
4218                yDir->isGray = 0;
4219        }
4220    else
4221        {
4222                xDir->pixelBitCount = pixelBitCount[rasterType+1];
4223                yDir->pixelBitCount = pixelBitCount[rasterType+1];
4224                xDir->grayPreShift  = task->grayShift - task->grayShift * xGrayType / 3;
4225                yDir->grayPreShift  = task->grayShift - task->grayShift * yGrayType / 3;
4226                xDir->grayPostShift = task->grayShift - xDir->grayPreShift;
4227                yDir->grayPostShift = task->grayShift - yDir->grayPreShift;
4228                xDir->graySubHalf   = _UT_HALF_PIXEL;
4229                yDir->graySubHalf   = _UT_HALF_PIXEL;
4230                xDir->graySubPix    = _UT_ONE_PIXEL - 1;
4231                yDir->graySubPix    = _UT_ONE_PIXEL - 1;
4232                xDir->isGray = xDir->grayPreShift;
4233                yDir->isGray = yDir->grayPreShift;
4234                if      (fc->subPixelType == _UT_SUBPIXEL_TYPE_HORI) xDir->subPixelScale = 3;
4235                else if (fc->subPixelType == _UT_SUBPIXEL_TYPE_VERT) yDir->subPixelScale = 3;
4236                if (xDir->isGray)
4237                {
4238                        xDir->gridFitSize <<= xDir->grayPreShift;
4239                        xDir->graySubHalf = _UT_HALF_PIXEL << xDir->grayPreShift;
4240                        xDir->graySubPix  = (_UT_ONE_PIXEL << xDir->grayPreShift) - 1;
4241                }
4242                if (yDir->isGray)
4243                {
4244                        yDir->gridFitSize <<= yDir->grayPreShift;
4245                        yDir->graySubHalf = _UT_HALF_PIXEL << yDir->grayPreShift;
4246                        yDir->graySubPix  = (_UT_ONE_PIXEL << yDir->grayPreShift) - 1;
4247                }
4248    }
4249        task->compelPackedImage = compelPack[rasterType+1];
4250        task->isDropout = !fc->preventDropout && ((xDir->gridFitSize < 30) || (yDir->gridFitSize < 30));
4251        task->LineTo = ut_LineTo_Standard;
4252#ifdef _UT_USE_DROPOUT_COLTROL
4253        if (task->isDropout) task->LineTo = ut_LineTo_Dropout;
4254#endif
4255        if (fc->glyph->cmap->isStroke)
4256        {
4257                int strokeDepth = (yDir->gridFitSize / 20) + 1;
4258                if (strokeDepth < yDir->pixelBitCount) strokeDepth = yDir->pixelBitCount;
4259                strokeDepth = ((strokeDepth + (yDir->pixelBitCount/2)) / yDir->pixelBitCount) * yDir->pixelBitCount;
4260                ut_InitStrokeMask(&fc->strokeMask, strokeDepth);
4261                task->strokeMask = &fc->strokeMask;
4262                xDir->gridFitSize--;
4263                yDir->gridFitSize--;
4264                xDir->gridFitSize--;
4265                yDir->gridFitSize--;
4266        }
4267        UT_TRACE2("task->xSize = %d", task->xSize);
4268        UT_TRACE2("task->ySize = %d", task->ySize);
4269        UT_TRACE2("task->xDir.gridFitSize = %d", task->xDir.gridFitSize);
4270        UT_TRACE2("task->yDir.gridFitSize = %d", task->yDir.gridFitSize);
4271        UT_TRACE2("task->xDir.graySubHalf = %d", task->xDir.graySubHalf);
4272        UT_TRACE2("task->yDir.graySubHalf = %d", task->yDir.graySubHalf);
4273        UT_TRACE2("task->xDir.graySubPix  = %d", task->xDir.graySubPix );
4274        UT_TRACE2("task->yDir.graySubPix  = %d", task->yDir.graySubPix );
4275        UT_TRACE2("task->isDropout   = %d", task->isDropout);
4276        if (task->emulEdge || task->emulOutline) task->compelPackedImage = 0;
4277    task->rootGlyph.nPath  = 0;
4278    task->rootGlyph.nPoint = 0;
4279    task->workGlyph = task->rootGlyph;
4280        task->isBezier  = fc->glyph->cmap->glyphType == _UT_OUTLINE_TYPE_BEZIER;
4281        task->emSize    = ut_SWAP_U16(fc->glyph->cmap->depend.emSize);
4282        image->width    = (fc->glyph->width * fc->xSize + (task->emSize>>1)) / task->emSize;
4283        if (fc->fixedWidth)
4284        {
4285                int n = (image->width + (fc->fixedWidth>>1)) / fc->fixedWidth;
4286                image->width = fc->fixedWidth * n;
4287        }
4288        image->height   = (fc->glyph->height * fc->ySize + (task->emSize>>1)) / task->emSize;
4289        if (!fc->glyph->count)
4290        {
4291                image->type = _UT_IMAGE_TYPE_NULL;
4292                image->bbox.ox = 0;
4293                image->bbox.oy = 0;
4294                image->bbox.sx = 0;
4295                image->bbox.sy = 0;
4296                image->bSize = 0;
4297                image->lSize = 0;
4298                UT_TRACE_TAB_DEC();
4299                return _UT_TRUE;
4300        }
4301        if (!ut_InterpreteGlyph(fc))
4302        {
4303                UT_TRACE_TAB_DEC();
4304                return _UT_FALSE;
4305        }
4306        if (xDir->grayPostShift)
4307        {
4308                int i;
4309                for (i=0; i<task->rootGlyph.nPoint; i++)
4310                {
4311                        task->rootGlyph.x[i] <<= xDir->grayPostShift;
4312                }
4313        }
4314        if (yDir->grayPostShift)
4315        {
4316                int i;
4317                for (i=0; i<task->rootGlyph.nPoint; i++)
4318                {
4319                        task->rootGlyph.y[i] <<= yDir->grayPostShift;
4320                }
4321        }
4322        if (xDir->subPixelScale)
4323        {
4324                int i;
4325                for (i=0; i<task->rootGlyph.nPoint; i++)
4326                {
4327                        task->rootGlyph.x[i] *= 3;
4328                }
4329        }
4330        if (yDir->subPixelScale)
4331        {
4332                int i;
4333                for (i=0; i<task->rootGlyph.nPoint; i++)
4334                {
4335                        task->rootGlyph.y[i] *= 3;
4336                }
4337        }
4338        result = ut_PrepareOutlineGlyphImage(fc, image);
4339        UT_TRACE_TAB_DEC();
4340        return result;
4341}
4342
4343UT_BOOL utm_MakeImageOfOutlineFont(UT_FC* fc, UT_IMAGE* image)
4344{
4345        UT_FONT_TASK* task = fc->task;
4346        UT_TRACE1("ut_MakeOutlineGlyphImage()");
4347        if (image->type == _UT_IMAGE_TYPE_NULL_GLYPH) return _UT_TRUE;
4348        if (image->type == _UT_IMAGE_TYPE_NULL) return _UT_TRUE;
4349        if (image->type == _UT_RASTER_TYPE_OUTLINE) return _UT_TRUE;
4350        UT_TRACE_TAB_INC();
4351        if (fc->glyph->cmap->isStroke)
4352        {
4353                task->LineTo = ut_LineTo_Stroke;
4354                task->image = (UT_U32*)ut_AllocScanBuffer(task, image, task->i_lSize<<2);
4355                UT_MEMSET(task->image, 0, task->i_lSize<<2);
4356                ut_ScanGlyph(task, _UT_FALSE);
4357                ut_SwapImage(task);
4358                ut_CompleteImage(task, image);
4359        }
4360        else
4361        {
4362                if (ut_IsByteImage(fc))
4363                {
4364                        task->edge = (char*)ut_AllocScanBuffer(task, image, task->horiScanBufferSize+task->vertScanBufferSize);
4365                        UT_MEMSET(image->data, 0, image->lSize);
4366                        ut_ScanGlyph(task, _UT_TRUE);
4367                        ut_ScanFillGray(task, image->data);
4368                }
4369                else
4370                {
4371                        task->image = (UT_U32*)ut_AllocScanBuffer(task, image, (task->i_lSize<<2)+task->horiScanBufferSize+task->vertScanBufferSize);
4372                        task->edge = (char*)(task->image + task->i_lSize);
4373                        UT_MEMSET(task->image, 0, task->i_lSize<<2);
4374                        ut_ScanGlyph(task, _UT_TRUE);
4375                        ut_ScanFillMono(task);
4376                        ut_SwapImage(task);
4377                        ut_CompleteImage(task, image);
4378                }
4379                if (task->emulBold)
4380                {
4381                        if (image->width) if (!fc->isFixedPitch) image->width += ut_BoldExtra(fc->xSize);
4382                        task->emulBold = 0;
4383                }
4384                ut_BitmapEffect(fc, image);
4385        }
4386        UT_TRACE_TAB_DEC();
4387    return _UT_TRUE;
4388}
4389
4390/***************************************************************************/
4391
4392UT_BOOL utm_PrepareCharImageFromOutlineFont(UT_FC* fc, UT_CODE code, UT_IMAGE* image)
4393{
4394        UT_BOOL result;
4395        UT_TRACE2("utm_PrepareCharImageFromOutlineFont() code = %d", code);
4396        UT_TRACE_TAB_INC();
4397    if (code == _UT_INVALID_CODE)
4398    {
4399        image->type = _UT_IMAGE_TYPE_NULL_GLYPH;
4400                UT_TRACE_TAB_DEC();
4401        return _UT_FALSE;
4402    }
4403        if (!utm_GetGlyph(fc, code, fc->glyph))
4404        {
4405        image->type = _UT_IMAGE_TYPE_NULL_GLYPH;
4406                UT_TRACE_TAB_DEC();
4407                return _UT_FALSE;
4408        }
4409        result = ut_PrepareRasterGlyphOutline(fc, image);
4410        UT_TRACE_TAB_DEC();
4411        return result;
4412}
4413
4414UT_BOOL utm_GetCharImageFromOutlineFont(UT_FC* fc, UT_CODE code, UT_IMAGE* image)
4415{
4416        #ifdef _UT_USE_CACHE
4417                if (utm_CacheHit(fc, code, image)) return _UT_TRUE;
4418        #endif /*#ifdef _UT_USE_CACHE*/
4419        if (!utm_PrepareCharImageFromOutlineFont(fc, code, image)) return _UT_FALSE;
4420        if (!utm_MakeImageOfOutlineFont(fc, image)) return _UT_FALSE;
4421        #ifdef _UT_USE_CACHE
4422                utm_CacheAdd(fc, code, image);
4423        #endif /*#ifdef _UT_USE_CACHE*/
4424        return _UT_TRUE;
4425}
4426
4427UT_BOOL utm_PrepareCharImage(UT_FC* fc, UT_CODE code, UT_IMAGE* image)
4428{
4429        UT_FONT_TASK* task = fc->task;
4430        UT_TRACE2("utm_PrepareCharImage() code = %d", code);
4431        UT_TRACE_TAB_INC();
4432    if (code == _UT_INVALID_CODE)
4433    {
4434                UT_TRACE1("image->type = _UT_INVALID_CODE");
4435        image->type = _UT_IMAGE_TYPE_NULL_GLYPH;
4436                UT_TRACE_TAB_DEC();
4437        return _UT_FALSE;
4438    }
4439        if (!utm_GetGlyph(fc, code, fc->glyph))
4440        {
4441                UT_TRACE1("image->type = _UT_IMAGE_TYPE_NULL_GLYPH");
4442        image->type = _UT_IMAGE_TYPE_NULL_GLYPH;
4443                UT_TRACE_TAB_DEC();
4444                return _UT_FALSE;
4445        }
4446        task->emulItalic = fc->isItalic && !fc->fontItalic;
4447        task->emulBold   = fc->isBold   && (fc->fontWeight < _UT_FONT_WEIGHT_BOLD);
4448    task->emulEdge   = fc->edgeType;
4449    task->emulSmooth = (fc->rasterType == _UT_RASTER_TYPE_GRAY_2) ? fc->smoothType : 0;
4450        if ((fc->edgeType == _UT_EDGE_TYPE_OUTLINE) || (fc->edgeType == _UT_EDGE_TYPE_OUTLINE1)) task->emulOutline = 1;
4451        else if (fc->edgeType == _UT_EDGE_TYPE_INLINE) task->emulOutline = -1;
4452        else task->emulOutline = 0;
4453        if (fc->glyph->cmap->glyphType < 0)
4454        {
4455                UT_BOOL result = ut_PrepareRasterGlyphOutline(fc, image);
4456                UT_TRACE_TAB_DEC();
4457                return result;
4458        }
4459        else
4460        {
4461                #ifdef _UT_USE_BITMAP_FONT
4462                        UT_BOOL result = ut_PrepareRasterGlyphBitmap(fc, image);
4463                        UT_TRACE_TAB_DEC();
4464                        return result;
4465                #else /*#ifdef _UT_USE_BITMAP_FONT*/
4466                        UT_TRACE_TAB_DEC();
4467                        return _UT_FALSE;
4468                #endif /*#ifdef _UT_USE_BITMAP_FONT*/
4469        }
4470}
4471
4472UT_BOOL utm_MakeCharImage(UT_FC* fc, UT_IMAGE* image)
4473{
4474        if (fc->glyph->cmap->glyphType < 0)
4475        {
4476                return utm_MakeImageOfOutlineFont(fc, image);
4477        }
4478        else
4479        {
4480                #ifdef _UT_USE_BITMAP_FONT
4481                return utm_MakeImageOfBitmapFont(fc, image);
4482                #else /*#ifdef _UT_USE_BITMAP_FONT*/
4483                        UT_TRACE_TAB_DEC();
4484                        return _UT_FALSE;
4485                #endif /*#ifdef _UT_USE_BITMAP_FONT*/
4486        }
4487}
4488
4489UT_BOOL utm_GetCharImage(UT_FC* fc, UT_CODE code, UT_IMAGE* image)
4490{
4491        #ifdef _UT_USE_CACHE
4492                if (utm_CacheHit(fc, code, image)) return _UT_TRUE;
4493        #endif /*#ifdef _UT_USE_CACHE*/
4494        if (!utm_PrepareCharImage(fc, code, image)) return _UT_FALSE;
4495        if (fc->glyph->cmap->glyphType < 0)
4496        {
4497                if (!utm_MakeImageOfOutlineFont(fc, image)) return _UT_FALSE;
4498                #ifdef _UT_USE_CACHE
4499                        utm_CacheAdd(fc, code, image);
4500                #endif /*#ifdef _UT_USE_CACHE*/
4501                return _UT_TRUE;
4502        }
4503        else
4504        {
4505                #ifdef _UT_USE_BITMAP_FONT
4506                        if (!utm_MakeImageOfBitmapFont(fc, image)) return _UT_FALSE;
4507                        return _UT_TRUE;
4508                #else /*#ifdef _UT_USE_BITMAP_FONT*/
4509                        UT_TRACE_TAB_DEC();
4510                        return _UT_FALSE;
4511                #endif /*#ifdef _UT_USE_BITMAP_FONT*/
4512        }
4513}
4514
4515/***************************************************************************/
Note: See TracBrowser for help on using the repository browser.