[WIN32SS][FONT] Fix font metrics (#713)
[reactos.git] / win32ss / gdi / eng / lineto.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Line functions
5 * FILE: win32ss/gdi/eng/lineto.c
6 * PROGRAMER: ReactOS Team
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 static void FASTCALL
15 TranslateRects(RECT_ENUM *RectEnum, POINTL* Translate)
16 {
17 RECTL* CurrentRect;
18
19 if (0 != Translate->x || 0 != Translate->y)
20 {
21 for (CurrentRect = RectEnum->arcl; CurrentRect < RectEnum->arcl + RectEnum->c; CurrentRect++)
22 {
23 CurrentRect->left += Translate->x;
24 CurrentRect->right += Translate->x;
25 CurrentRect->top += Translate->y;
26 CurrentRect->bottom += Translate->y;
27 }
28 }
29 }
30
31 LONG
32 HandleStyles(
33 BRUSHOBJ *pbo,
34 POINTL* Translate,
35 LONG x,
36 LONG y,
37 LONG deltax,
38 LONG deltay,
39 LONG dx,
40 LONG dy,
41 PULONG piStyle)
42 {
43 PEBRUSHOBJ pebo = (PEBRUSHOBJ)pbo;
44 PULONG pulStyles = pebo->pbrush->pStyle;
45 ULONG iStyle, cStyles = pebo->pbrush->dwStyleCount;
46 LONG diStyle, offStyle, lStyleMax;
47
48 if (cStyles > 0)
49 {
50 if (deltax > deltay)
51 {
52 offStyle = (- Translate->x) % pebo->pbrush->ulStyleSize;
53 diStyle = dx;
54 lStyleMax = x;
55 }
56 else
57 {
58 offStyle = (- Translate->y) % pebo->pbrush->ulStyleSize;
59 diStyle = dy;
60 lStyleMax = y;
61 }
62
63 /* Now loop until we have found the style index */
64 for (iStyle = 0; offStyle >= pulStyles[iStyle]; iStyle++)
65 {
66 offStyle -= pulStyles[iStyle];
67 }
68
69 if (diStyle > 0)
70 {
71 lStyleMax += pulStyles[iStyle] - offStyle;
72 }
73 else
74 {
75 lStyleMax -= offStyle + 1;
76 }
77 }
78 else
79 {
80 iStyle = 0;
81 lStyleMax = MAX_COORD;
82 }
83
84 *piStyle = iStyle;
85 return lStyleMax;
86 }
87
88 /*
89 * Draw a line from top-left to bottom-right
90 */
91 void FASTCALL
92 NWtoSE(SURFOBJ* OutputObj, CLIPOBJ* Clip,
93 BRUSHOBJ* pbo, LONG x, LONG y, LONG deltax, LONG deltay,
94 POINTL* Translate)
95 {
96 int i;
97 int error;
98 BOOLEAN EnumMore;
99 RECTL* ClipRect;
100 RECT_ENUM RectEnum;
101 ULONG Pixel = pbo->iSolidColor;
102 LONG delta;
103 PEBRUSHOBJ pebo = (PEBRUSHOBJ)pbo;
104 PULONG pulStyles = pebo->pbrush->pStyle;
105 ULONG iStyle, cStyles = pebo->pbrush->dwStyleCount;
106 LONG lStyleMax;
107
108 lStyleMax = HandleStyles(pbo, Translate, x, y, deltax, deltay, 1, 1, &iStyle);
109
110 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
111 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
112 TranslateRects(&RectEnum, Translate);
113 ClipRect = RectEnum.arcl;
114 delta = max(deltax, deltay);
115 i = 0;
116 error = delta >> 1;
117 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
118 {
119 while ((ClipRect < RectEnum.arcl + RectEnum.c /* there's still a current clip rect */
120 && (ClipRect->bottom <= y /* but it's above us */
121 || (ClipRect->top <= y && ClipRect->right <= x))) /* or to the left of us */
122 || EnumMore) /* no current clip rect, but rects left */
123 {
124 /* Skip to the next clip rect */
125 if (RectEnum.arcl + RectEnum.c <= ClipRect)
126 {
127 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
128 TranslateRects(&RectEnum, Translate);
129 ClipRect = RectEnum.arcl;
130 }
131 else
132 {
133 ClipRect++;
134 }
135 }
136 if (ClipRect < RectEnum.arcl + RectEnum.c) /* If there's no current clip rect we're done */
137 {
138 if ((ClipRect->left <= x && ClipRect->top <= y) && ((iStyle & 1) == 0))
139 {
140 DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_PutPixel(
141 OutputObj, x, y, Pixel);
142 }
143 if (deltax < deltay)
144 {
145 y++;
146 if (y == lStyleMax)
147 {
148 iStyle = (iStyle + 1) % cStyles;
149 lStyleMax = y + pulStyles[iStyle];
150 }
151 error = error + deltax;
152 if (deltay <= error)
153 {
154 x++;
155 error = error - deltay;
156 }
157 }
158 else
159 {
160 x++;
161 if (x == lStyleMax)
162 {
163 iStyle = (iStyle + 1) % cStyles;
164 lStyleMax = x + pulStyles[iStyle];
165 }
166 error = error + deltay;
167 if (deltax <= error)
168 {
169 y++;
170 error = error - deltax;
171 }
172 }
173 i++;
174 }
175 }
176 }
177
178 void FASTCALL
179 SWtoNE(SURFOBJ* OutputObj, CLIPOBJ* Clip,
180 BRUSHOBJ* pbo, LONG x, LONG y, LONG deltax, LONG deltay,
181 POINTL* Translate)
182 {
183 int i;
184 int error;
185 BOOLEAN EnumMore;
186 RECTL* ClipRect;
187 RECT_ENUM RectEnum;
188 ULONG Pixel = pbo->iSolidColor;
189 LONG delta;
190 PEBRUSHOBJ pebo = (PEBRUSHOBJ)pbo;
191 PULONG pulStyles = pebo->pbrush->pStyle;
192 ULONG iStyle, cStyles = pebo->pbrush->dwStyleCount;
193 LONG lStyleMax;
194
195 lStyleMax = HandleStyles(pbo, Translate, x, y, deltax, deltay, 1, -1, &iStyle);
196
197 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTUP, 0);
198 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
199 TranslateRects(&RectEnum, Translate);
200 ClipRect = RectEnum.arcl;
201 delta = max(deltax, deltay);
202 i = 0;
203 error = delta >> 1;
204 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
205 {
206 while ((ClipRect < RectEnum.arcl + RectEnum.c
207 && (y < ClipRect->top
208 || (y < ClipRect->bottom && ClipRect->right <= x)))
209 || EnumMore)
210 {
211 if (RectEnum.arcl + RectEnum.c <= ClipRect)
212 {
213 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
214 TranslateRects(&RectEnum, Translate);
215 ClipRect = RectEnum.arcl;
216 }
217 else
218 {
219 ClipRect++;
220 }
221 }
222 if (ClipRect < RectEnum.arcl + RectEnum.c)
223 {
224 if ((ClipRect->left <= x && y < ClipRect->bottom) && ((iStyle & 1) == 0))
225 {
226 DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_PutPixel(
227 OutputObj, x, y, Pixel);
228 }
229 if (deltax < deltay)
230 {
231 y--;
232 if (y == lStyleMax)
233 {
234 iStyle = (iStyle - 1) % cStyles;
235 lStyleMax = y - pulStyles[iStyle];
236 }
237 error = error + deltax;
238 if (deltay <= error)
239 {
240 x++;
241 error = error - deltay;
242 }
243 }
244 else
245 {
246 x++;
247 if (x == lStyleMax)
248 {
249 iStyle = (iStyle + 1) % cStyles;
250 lStyleMax = x + pulStyles[iStyle];
251 }
252 error = error + deltay;
253 if (deltax <= error)
254 {
255 y--;
256 error = error - deltax;
257 }
258 }
259 i++;
260 }
261 }
262 }
263
264 void FASTCALL
265 NEtoSW(SURFOBJ* OutputObj, CLIPOBJ* Clip,
266 BRUSHOBJ* pbo, LONG x, LONG y, LONG deltax, LONG deltay,
267 POINTL* Translate)
268 {
269 int i;
270 int error;
271 BOOLEAN EnumMore;
272 RECTL* ClipRect;
273 RECT_ENUM RectEnum;
274 ULONG Pixel = pbo->iSolidColor;
275 LONG delta;
276 PEBRUSHOBJ pebo = (PEBRUSHOBJ)pbo;
277 PULONG pulStyles = pebo->pbrush->pStyle;
278 ULONG iStyle, cStyles = pebo->pbrush->dwStyleCount;
279 LONG lStyleMax;
280
281 lStyleMax = HandleStyles(pbo, Translate, x, y, deltax, deltay, -1, 1, &iStyle);
282
283 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTDOWN, 0);
284 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
285 TranslateRects(&RectEnum, Translate);
286 ClipRect = RectEnum.arcl;
287 delta = max(deltax, deltay);
288 i = 0;
289 error = delta >> 1;
290 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
291 {
292 while ((ClipRect < RectEnum.arcl + RectEnum.c
293 && (ClipRect->bottom <= y
294 || (ClipRect->top <= y && x < ClipRect->left)))
295 || EnumMore)
296 {
297 if (RectEnum.arcl + RectEnum.c <= ClipRect)
298 {
299 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
300 TranslateRects(&RectEnum, Translate);
301 ClipRect = RectEnum.arcl;
302 }
303 else
304 {
305 ClipRect++;
306 }
307 }
308 if (ClipRect < RectEnum.arcl + RectEnum.c)
309 {
310 if ((x < ClipRect->right && ClipRect->top <= y) && ((iStyle & 1) == 0))
311 {
312 DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_PutPixel(
313 OutputObj, x, y, Pixel);
314 }
315 if (deltax < deltay)
316 {
317 y++;
318 if (y == lStyleMax)
319 {
320 iStyle = (iStyle + 1) % cStyles;
321 lStyleMax = y + pulStyles[iStyle];
322 }
323 error = error + deltax;
324 if (deltay <= error)
325 {
326 x--;
327 error = error - deltay;
328 }
329 }
330 else
331 {
332 x--;
333 if (x == lStyleMax)
334 {
335 iStyle = (iStyle - 1) % cStyles;
336 lStyleMax = x - pulStyles[iStyle];
337 }
338 error = error + deltay;
339 if (deltax <= error)
340 {
341 y++;
342 error = error - deltax;
343 }
344 }
345 i++;
346 }
347 }
348 }
349
350 void FASTCALL
351 SEtoNW(SURFOBJ* OutputObj, CLIPOBJ* Clip,
352 BRUSHOBJ* pbo, LONG x, LONG y, LONG deltax, LONG deltay,
353 POINTL* Translate)
354 {
355 int i;
356 int error;
357 BOOLEAN EnumMore;
358 RECTL* ClipRect;
359 RECT_ENUM RectEnum;
360 ULONG Pixel = pbo->iSolidColor;
361 LONG delta;
362 PEBRUSHOBJ pebo = (PEBRUSHOBJ)pbo;
363 PULONG pulStyles = pebo->pbrush->pStyle;
364 ULONG iStyle, cStyles = pebo->pbrush->dwStyleCount;
365 LONG lStyleMax;
366
367 lStyleMax = HandleStyles(pbo, Translate, x, y, deltax, deltay, -1, -1, &iStyle);
368
369 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTUP, 0);
370 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
371 TranslateRects(&RectEnum, Translate);
372 ClipRect = RectEnum.arcl;
373 delta = max(deltax, deltay);
374 i = 0;
375 error = delta >> 1;
376 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
377 {
378 while ((ClipRect < RectEnum.arcl + RectEnum.c
379 && (y < ClipRect->top
380 || (y < ClipRect->bottom && x < ClipRect->left)))
381 || EnumMore)
382 {
383 if (RectEnum.arcl + RectEnum.c <= ClipRect)
384 {
385 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
386 TranslateRects(&RectEnum, Translate);
387 ClipRect = RectEnum.arcl;
388 }
389 else
390 {
391 ClipRect++;
392 }
393 }
394 if (ClipRect < RectEnum.arcl + RectEnum.c)
395 {
396 if ((x < ClipRect->right && y < ClipRect->bottom) && ((iStyle & 1) == 0))
397 {
398 DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_PutPixel(
399 OutputObj, x, y, Pixel);
400 }
401 if (deltax < deltay)
402 {
403 y--;
404 if (y == lStyleMax)
405 {
406 iStyle = (iStyle - 1) % cStyles;
407 lStyleMax = y - pulStyles[iStyle];
408 }
409 error = error + deltax;
410 if (deltay <= error)
411 {
412 x--;
413 error = error - deltay;
414 }
415 }
416 else
417 {
418 x--;
419 if (x == lStyleMax)
420 {
421 iStyle = (iStyle - 1) % cStyles;
422 lStyleMax = x - pulStyles[iStyle];
423 }
424 error = error + deltay;
425 if (deltax <= error)
426 {
427 y--;
428 error = error - deltax;
429 }
430 }
431 i++;
432 }
433 }
434 }
435
436 /*
437 * @implemented
438 */
439 BOOL APIENTRY
440 EngLineTo(
441 _Inout_ SURFOBJ *DestObj,
442 _In_ CLIPOBJ *Clip,
443 _In_ BRUSHOBJ *pbo,
444 _In_ LONG x1,
445 _In_ LONG y1,
446 _In_ LONG x2,
447 _In_ LONG y2,
448 _In_opt_ RECTL *RectBounds,
449 _In_ MIX mix)
450 {
451 LONG x, y, deltax, deltay, xchange, ychange, hx, vy;
452 ULONG i;
453 ULONG Pixel = pbo->iSolidColor;
454 SURFOBJ *OutputObj;
455 RECTL DestRect;
456 POINTL Translate;
457 INTENG_ENTER_LEAVE EnterLeave;
458 RECT_ENUM RectEnum;
459 BOOL EnumMore;
460 CLIPOBJ *pcoPriv = NULL;
461 PEBRUSHOBJ pebo = (PEBRUSHOBJ)pbo;
462 ULONG cStyles = pebo->pbrush->dwStyleCount;
463
464 if (x1 < x2)
465 {
466 DestRect.left = x1;
467 DestRect.right = x2;
468 }
469 else
470 {
471 DestRect.left = x2;
472 DestRect.right = x1 + 1;
473 }
474 if (y1 < y2)
475 {
476 DestRect.top = y1;
477 DestRect.bottom = y2;
478 }
479 else
480 {
481 DestRect.top = y2;
482 DestRect.bottom = y1 + 1;
483 }
484
485 if (! IntEngEnter(&EnterLeave, DestObj, &DestRect, FALSE, &Translate, &OutputObj))
486 {
487 return FALSE;
488 }
489
490 if (!Clip)
491 {
492 Clip = pcoPriv = EngCreateClip();
493 if (!Clip)
494 {
495 return FALSE;
496 }
497 IntEngUpdateClipRegion((XCLIPOBJ*)Clip, 0, 0, RectBounds);
498 }
499
500 x1 += Translate.x;
501 x2 += Translate.x;
502 y1 += Translate.y;
503 y2 += Translate.y;
504
505 x = x1;
506 y = y1;
507 deltax = x2 - x1;
508 deltay = y2 - y1;
509
510 if (0 == deltax && 0 == deltay)
511 {
512 return TRUE;
513 }
514
515 if (deltax < 0)
516 {
517 xchange = -1;
518 deltax = - deltax;
519 hx = x2 + 1;
520 }
521 else
522 {
523 xchange = 1;
524 hx = x1;
525 }
526
527 if (deltay < 0)
528 {
529 ychange = -1;
530 deltay = - deltay;
531 vy = y2 + 1;
532 }
533 else
534 {
535 ychange = 1;
536 vy = y1;
537 }
538
539 if ((y1 == y2) && (cStyles == 0))
540 {
541 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
542 do
543 {
544 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
545 for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top + Translate.y <= y1; i++)
546 {
547 if (y1 < RectEnum.arcl[i].bottom + Translate.y &&
548 RectEnum.arcl[i].left + Translate.x <= hx + deltax &&
549 hx < RectEnum.arcl[i].right + Translate.x &&
550 max(hx, RectEnum.arcl[i].left + Translate.x) <
551 min(hx + deltax, RectEnum.arcl[i].right + Translate.x))
552 {
553 DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_HLine(
554 OutputObj,
555 max(hx, RectEnum.arcl[i].left + Translate.x),
556 min(hx + deltax, RectEnum.arcl[i].right + Translate.x),
557 y1, Pixel);
558 }
559 }
560 }
561 while (EnumMore);
562 }
563 else if ((x1 == x2) && (cStyles == 0))
564 {
565 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
566 do
567 {
568 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
569 for (i = 0; i < RectEnum.c; i++)
570 {
571 if (RectEnum.arcl[i].left + Translate.x <= x1 &&
572 x1 < RectEnum.arcl[i].right + Translate.x &&
573 RectEnum.arcl[i].top + Translate.y <= vy + deltay &&
574 vy < RectEnum.arcl[i].bottom + Translate.y)
575 {
576 DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_VLine(
577 OutputObj, x1,
578 max(vy, RectEnum.arcl[i].top + Translate.y),
579 min(vy + deltay, RectEnum.arcl[i].bottom + Translate.y),
580 Pixel);
581 }
582 }
583 }
584 while (EnumMore);
585 }
586 else
587 {
588 if (0 < xchange)
589 {
590 if (0 < ychange)
591 {
592 NWtoSE(OutputObj, Clip, pbo, x, y, deltax, deltay, &Translate);
593 }
594 else
595 {
596 SWtoNE(OutputObj, Clip, pbo, x, y, deltax, deltay, &Translate);
597 }
598 }
599 else
600 {
601 if (0 < ychange)
602 {
603 NEtoSW(OutputObj, Clip, pbo, x, y, deltax, deltay, &Translate);
604 }
605 else
606 {
607 SEtoNW(OutputObj, Clip, pbo, x, y, deltax, deltay, &Translate);
608 }
609 }
610 }
611
612 if (pcoPriv)
613 {
614 EngDeleteClip(pcoPriv);
615 }
616
617 return IntEngLeave(&EnterLeave);
618 }
619
620 BOOL APIENTRY
621 IntEngLineTo(SURFOBJ *psoDest,
622 CLIPOBJ *ClipObj,
623 BRUSHOBJ *pbo,
624 LONG x1,
625 LONG y1,
626 LONG x2,
627 LONG y2,
628 RECTL *RectBounds,
629 MIX Mix)
630 {
631 BOOLEAN ret;
632 SURFACE *psurfDest;
633 PEBRUSHOBJ GdiBrush;
634 RECTL b;
635
636 ASSERT(psoDest);
637 psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
638 ASSERT(psurfDest);
639
640 GdiBrush = CONTAINING_RECORD(
641 pbo,
642 EBRUSHOBJ,
643 BrushObject);
644 ASSERT(GdiBrush);
645 ASSERT(GdiBrush->pbrush);
646
647 if (GdiBrush->pbrush->flAttrs & BR_IS_NULL)
648 return TRUE;
649
650 /* No success yet */
651 ret = FALSE;
652
653 /* Clip lines totally outside the clip region. This is not done as an
654 * optimization (there are very few lines drawn outside the region) but
655 * as a workaround for what seems to be a problem in the CL54XX driver */
656 if (NULL == ClipObj || DC_TRIVIAL == ClipObj->iDComplexity)
657 {
658 b.left = 0;
659 b.right = psoDest->sizlBitmap.cx;
660 b.top = 0;
661 b.bottom = psoDest->sizlBitmap.cy;
662 }
663 else
664 {
665 b = ClipObj->rclBounds;
666 }
667 if ((x1 < b.left && x2 < b.left) || (b.right <= x1 && b.right <= x2) ||
668 (y1 < b.top && y2 < b.top) || (b.bottom <= y1 && b.bottom <= y2))
669 {
670 return TRUE;
671 }
672
673 b.left = min(x1, x2);
674 b.right = max(x1, x2);
675 b.top = min(y1, y2);
676 b.bottom = max(y1, y2);
677 if (b.left == b.right) b.right++;
678 if (b.top == b.bottom) b.bottom++;
679
680 if (psurfDest->flags & HOOK_LINETO)
681 {
682 /* Call the driver's DrvLineTo */
683 ret = GDIDEVFUNCS(psoDest).LineTo(
684 psoDest, ClipObj, pbo, x1, y1, x2, y2, &b, Mix);
685 }
686
687 #if 0
688 if (! ret && (psurfDest->flags & HOOK_STROKEPATH))
689 {
690 /* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */
691 }
692 #endif
693
694 if (! ret)
695 {
696 ret = EngLineTo(psoDest, ClipObj, pbo, x1, y1, x2, y2, RectBounds, Mix);
697 }
698
699 return ret;
700 }
701
702 BOOL APIENTRY
703 IntEngPolyline(SURFOBJ *psoDest,
704 CLIPOBJ *Clip,
705 BRUSHOBJ *pbo,
706 CONST LPPOINT pt,
707 LONG dCount,
708 MIX Mix)
709 {
710 LONG i;
711 RECTL rect;
712 BOOL ret = FALSE;
713
714 // Draw the Polyline with a call to IntEngLineTo for each segment.
715 for (i = 1; i < dCount; i++)
716 {
717 rect.left = min(pt[i-1].x, pt[i].x);
718 rect.top = min(pt[i-1].y, pt[i].y);
719 rect.right = max(pt[i-1].x, pt[i].x);
720 rect.bottom = max(pt[i-1].y, pt[i].y);
721 ret = IntEngLineTo(psoDest,
722 Clip,
723 pbo,
724 pt[i-1].x,
725 pt[i-1].y,
726 pt[i].x,
727 pt[i].y,
728 &rect,
729 Mix);
730 if (!ret)
731 {
732 break;
733 }
734 }
735
736 return ret;
737 }
738
739 /* EOF */