:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / dd / vga / display / objects / paint.c
1
2 #include "../vgaddi.h"
3 #include "../vgavideo/vgavideo.h"
4 #include "brush.h"
5
6 #include <debug.h>
7
8 BOOL VGADDIFillSolid(SURFOBJ *Surface, RECTL Dimensions, ULONG iColor)
9 {
10   int x, y, x2, y2, w, h;
11   ULONG offset, i, j, pre1;
12   ULONG orgpre1, orgx, midpre1, tmppre1;
13   ULONG ileftpix, imidpix, irightpix;
14   double leftpix, midpix, rightpix, temp;
15   UCHAR a;
16
17   DPRINT("VGADDIFillSolid: x:%d, y:%d, w:%d, h:%d\n", x, y, w, h);
18
19   // Swap dimensions so that x, y are at topmost left
20   if(Dimensions.right < Dimensions.left) {
21     x  = Dimensions.right;
22     x2 = Dimensions.left;
23   } else {
24     x2 = Dimensions.right;
25     x  = Dimensions.left;
26   }
27   if(Dimensions.bottom < Dimensions.top) {
28     y  = Dimensions.bottom;
29     y2 = Dimensions.top;
30   } else {
31     y2 = Dimensions.bottom;
32     y  = Dimensions.top;
33   }
34
35   // Calculate the width and height
36   w = x2 - x;
37   h = y2 - y;
38
39   // Calculate the starting offset
40   offset = xconv[x]+y80[y];
41
42   // Make a note of original x
43   orgx=x;
44
45   // If width is less than 8, draw using vertical lines
46   if(w<8)
47   {
48     for (i=x; i<x+w; i++)
49       vgaVLine(i, y, h, iColor);
50
51   // Otherwise, use the optimized code
52   } else {
53
54     // Calculate the left mask pixels, middle bytes and right mask pixel
55     leftpix = 8-mod(x, 8);
56     rightpix = mod(x+w, 8);
57     midpix = (w-leftpix-rightpix) / 8;
58
59     ileftpix = leftpix;
60     irightpix = rightpix;
61     imidpix = midpix;
62
63     pre1=xconv[x-(8-ileftpix)]+y80[y];
64     orgpre1=pre1;
65
66     if(ileftpix>0)
67     {
68       // Write left pixels
69       WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);     // set the mask
70       WRITE_PORT_UCHAR((PUCHAR)0x3cf,startmasks[ileftpix]);
71
72       tmppre1 = pre1;
73       for (j=y; j<y+h; j++)
74       {
75         a = READ_REGISTER_UCHAR(vidmem + tmppre1);
76         WRITE_REGISTER_UCHAR(vidmem + tmppre1, iColor);
77         tmppre1+=80;
78       }
79
80       // Prepare new x for the middle
81       x=orgx+8;
82     }
83
84     if(imidpix>0)
85     {
86       midpre1=xconv[x]+y80[y];
87
88       // Set mask to all pixels in byte
89       WRITE_PORT_UCHAR((PUCHAR)0x3ce, 0x08);
90
91       WRITE_PORT_UCHAR((PUCHAR)0x3cf, 0xff);
92
93       for (j=y; j<y+h; j++)
94       {
95         memset(vidmem+midpre1, iColor, imidpix); // write middle pixels, no need to read in latch because of the width
96         midpre1+=80;
97       }
98     }
99
100     x=orgx+w-irightpix;
101     pre1=xconv[x]+y80[y];
102
103     // Write right pixels
104     WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);     // set the mask bits
105     WRITE_PORT_UCHAR((PUCHAR)0x3cf,endmasks[irightpix]);
106
107     for (j=y; j<y+h; j++)
108     {
109       a = READ_REGISTER_UCHAR(vidmem + pre1);
110       WRITE_REGISTER_UCHAR(vidmem + pre1, iColor);
111       pre1+=80;
112     }
113   }
114
115   return TRUE;
116 }
117
118 BOOL VGADDIPaintRgn(SURFOBJ *Surface, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix,
119                     BRUSHINST *BrushInst, POINTL *BrushPoint)
120 {
121    RECT_ENUM RectEnum;
122    BOOL EnumMore;
123
124    DPRINT("VGADDIPaintRgn: iMode: %d, iDComplexity: %d\n Color:%d\n", ClipRegion->iMode, ClipRegion->iDComplexity, iColor);
125    switch(ClipRegion->iMode) {
126
127       case TC_RECTANGLES:
128
129       /* Rectangular clipping can be handled without enumeration.
130          Note that trivial clipping is not possible, since the clipping
131          region defines the area to fill */
132
133       if (ClipRegion->iDComplexity == DC_RECT)
134       {
135                  DPRINT("VGADDIPaintRgn Rect:%d %d %d %d\n", ClipRegion->rclBounds.left, ClipRegion->rclBounds.top, ClipRegion->rclBounds.right, ClipRegion->rclBounds.bottom);
136          VGADDIFillSolid(Surface, ClipRegion->rclBounds, iColor);
137       } else {
138          /* Enumerate all the rectangles and draw them */
139
140          CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY,
141                             ENUM_RECT_LIMIT);
142
143          do {
144                         int i;
145             EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum);
146                         DPRINT("EnumMore: %d, count: %d\n", EnumMore, RectEnum.c);
147                         for( i=0; i<RectEnum.c; i++){
148                       DPRINT("VGADDI enum Rect:%d %d %d %d\n", RectEnum.arcl[i].left, RectEnum.arcl[i].top, RectEnum.arcl[i].right, RectEnum.arcl[i].bottom);
149               VGADDIFillSolid(Surface, RectEnum.arcl[i], iColor);
150                         }
151
152          } while (EnumMore);
153       }
154
155       return(TRUE);
156
157       default:
158          return(FALSE);
159    }
160 }
161
162
163
164 BOOL STDCALL
165 DrvPaint(IN SURFOBJ *Surface,
166          IN CLIPOBJ *ClipRegion,
167          IN BRUSHOBJ *Brush,
168          IN POINTL *BrushOrigin,
169          IN MIX Mix)
170 {
171    ULONG iSolidColor;
172
173    iSolidColor = Brush->iSolidColor; // FIXME: Realizations and the like
174
175    // If the foreground and background Mixes are the same,
176    // (LATER or if there's no brush mask)
177    // then see if we can use the solid brush accelerators
178
179    // FIXME: Put in the mix switch below
180    // Brush color parameter doesn't matter for these rops
181    return(VGADDIPaintRgn(Surface, ClipRegion, iSolidColor, Mix, NULL, BrushOrigin));
182
183    if ((Mix & 0xFF) == ((Mix >> 8) & 0xFF))
184    {
185       switch (Mix & 0xFF)
186       {
187          case 0:
188             break;
189
190          // FIXME: Implement all these millions of ROPs
191          // For now we don't support brushes -- everything is solid
192
193          case R2_MASKNOTPEN:
194          case R2_NOTCOPYPEN:
195          case R2_XORPEN:
196          case R2_MASKPEN:
197          case R2_NOTXORPEN:
198          case R2_MERGENOTPEN:
199          case R2_COPYPEN:
200          case R2_MERGEPEN:
201          case R2_NOTMERGEPEN:
202          case R2_MASKPENNOT:
203          case R2_NOTMASKPEN:
204          case R2_MERGEPENNOT:
205
206          // Rops that are implicit solid colors
207          case R2_NOT:
208          case R2_WHITE:
209          case R2_BLACK:
210
211
212   // FIXME: The Paint region belongs HERE
213
214          case R2_NOP:
215             return(TRUE);
216
217          default:
218             break;
219       }
220    }
221
222 doBitBlt:
223
224    // If VGADDIPaint can't do it, VGADDIBitBlt can.. or it might just loop back
225    // here and we have a nice infinite loop
226
227 /*   return( VGADDIBitBlt(Surface, (SURFOBJ *)NULL, (SURFOBJ *)NULL, ClipRegion,
228                        (XLATEOBJ *)NULL, &ClipRegion->rclBounds,
229                        NULL, (POINTL *)NULL, Brush, BrushOrigin,
230                        NULL) ); UNIMPLEMENTED */
231 }