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