1 /*
2  * PROJECT:         ReactOS VGA display driver
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            win32ss/drivers/displays/vga/objects/paint.c
5  * PURPOSE:
6  * PROGRAMMERS:
7  */
8 
9 #include <vgaddi.h>
10 
11 #include "brush.h"
12 
13 BOOL VGADDIFillSolid(SURFOBJ *Surface, RECTL Dimensions, ULONG iColor)
14 {
15     int x, y, x2, y2, w, h, j;
16     ULONG orgx, pre1, midpre1, tmppre1;
17     //ULONG offset, orgpre1;
18     int ileftpix, imidpix, irightpix;
19 /*    double leftpix, midpix, rightpix;*/
20 
21     /* Swap dimensions so that x, y are at topmost left */
22     if ( Dimensions.right < Dimensions.left )
23     {
24         x  = Dimensions.right;
25         x2 = Dimensions.left;
26     }
27     else
28     {
29         x2 = Dimensions.right;
30         x  = Dimensions.left;
31     }
32     if ( Dimensions.bottom < Dimensions.top )
33     {
34         y  = Dimensions.bottom;
35         y2 = Dimensions.top;
36     }
37     else
38     {
39         y2 = Dimensions.bottom;
40         y  = Dimensions.top;
41     }
42 
43     /* Calculate the width and height */
44     w = x2 - x;
45     h = y2 - y;
46 
47     DPRINT("VGADDIFillSolid: x:%d, y:%d, w:%d, h:%d\n", x, y, w, h);
48 
49     /* Calculate the starting offset */
50     //offset = xconv[x]+y80[y];
51 
52     /* Make a note of original x */
53     orgx = x;
54 
55     /* Calculate the left mask pixels, middle bytes and right mask pixel */
56     ileftpix = 7 - mod8(x-1);
57     irightpix = mod8(x+w);
58     imidpix = (w-ileftpix-irightpix) / 8;
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             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             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         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(
133     IN SURFOBJ *Surface,
134     IN CLIPOBJ *ClipRegion,
135     IN ULONG iColor,
136     IN MIX Mix,
137     IN BRUSHINST *BrushInst,
138     IN POINTL *BrushPoint)
139 {
140     RECT_ENUM RectEnum;
141     BOOL EnumMore;
142 
143     DPRINT("VGADDIPaintRgn: iMode: %d, iDComplexity: %d\n Color:%d\n", ClipRegion->iMode, ClipRegion->iDComplexity, iColor);
144     switch(ClipRegion->iMode)
145     {
146         case TC_RECTANGLES:
147 
148         /* Rectangular clipping can be handled without enumeration.
149            Note that trivial clipping is not possible, since the clipping
150            region defines the area to fill */
151 
152         if (ClipRegion->iDComplexity == DC_RECT)
153         {
154             DPRINT("VGADDIPaintRgn Rect:%d %d %d %d\n", ClipRegion->rclBounds.left, ClipRegion->rclBounds.top, ClipRegion->rclBounds.right, ClipRegion->rclBounds.bottom);
155             VGADDIFillSolid(Surface, ClipRegion->rclBounds, iColor);
156         }
157         else
158         {
159             /* Enumerate all the rectangles and draw them */
160 
161             CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0);
162 
163             do
164             {
165                 UINT i;
166                 EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum);
167                 DPRINT("EnumMore: %d, count: %d\n", EnumMore, RectEnum.c);
168                 for( i=0; i<RectEnum.c; i++)
169                 {
170                     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);
171                     VGADDIFillSolid(Surface, RectEnum.arcl[i], iColor);
172                 }
173             } while (EnumMore);
174         }
175         return TRUE;
176 
177         default:
178             return FALSE;
179     }
180 }
181 
182 
183 BOOL APIENTRY
184 DrvPaint(
185     IN SURFOBJ *Surface,
186     IN CLIPOBJ *ClipRegion,
187     IN BRUSHOBJ *Brush,
188     IN POINTL *BrushOrigin,
189     IN MIX Mix)
190 {
191     ULONG iSolidColor;
192 
193     iSolidColor = Brush->iSolidColor; // FIXME: Realizations and the like
194 
195     // If the foreground and background Mixes are the same,
196     // (LATER or if there's no brush mask)
197     // then see if we can use the solid brush accelerators
198 
199     // FIXME: Put in the mix switch below
200     // Brush color parameter doesn't matter for these rops
201     return(VGADDIPaintRgn(Surface, ClipRegion, iSolidColor, Mix, NULL, BrushOrigin));
202 
203     if ((Mix & 0xFF) == ((Mix >> 8) & 0xFF))
204     {
205         switch (Mix & 0xFF)
206         {
207             case 0:
208                 break;
209 
210             // FIXME: Implement all these millions of ROPs
211             // For now we don't support brushes -- everything is solid
212 
213             case R2_MASKNOTPEN:
214             case R2_NOTCOPYPEN:
215             case R2_XORPEN:
216             case R2_MASKPEN:
217             case R2_NOTXORPEN:
218             case R2_MERGENOTPEN:
219             case R2_COPYPEN:
220             case R2_MERGEPEN:
221             case R2_NOTMERGEPEN:
222             case R2_MASKPENNOT:
223             case R2_NOTMASKPEN:
224             case R2_MERGEPENNOT:
225 
226             // Rops that are implicit solid colors
227             case R2_NOT:
228             case R2_WHITE:
229             case R2_BLACK:
230 
231 
232             // FIXME: The Paint region belongs HERE
233 
234             case R2_NOP:
235                 return TRUE;
236 
237             default:
238                 break;
239         }
240     }
241 
242 /*
243 doBitBlt:
244 
245     // If VGADDIPaint can't do it, VGADDIBitBlt can.. or it might just loop back
246     // here and we have a nice infinite loop
247 
248     return( VGADDIBitBlt(Surface, (SURFOBJ *)NULL, (SURFOBJ *)NULL, ClipRegion,
249                         (XLATEOBJ *)NULL, &ClipRegion->rclBounds,
250                         NULL, (POINTL *)NULL, Brush, BrushOrigin,
251                         NULL) ); UNIMPLEMENTED */
252 }
253