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