source: svn/newcon3bcm2_21bu/dst/dmw/src/grp/jungle_font/utfOutline.c

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