4 #include "GraphicsContext.h"
9 #define swap(a, b) { int temp = a; a = b; b = temp; }
12 GraphicsContext::GraphicsContext()
17 const unsigned kBottom
= 1;
18 const unsigned kTop
= 2;
19 const unsigned kLeft
= 4;
20 const unsigned kRight
= 8;
22 inline unsigned clipmask(int x
, int y
, const Rect
&rect
)
27 else if (x
> rect
.right
)
32 else if (y
> rect
.bottom
)
38 inline int vert_intersection(int x1
, int y1
, int x2
, int y2
, int x
)
40 return y1
+ (y2
- y1
) * (x
- x1
) / (x2
- x1
);
43 inline int horz_intersection(int x1
, int y1
, int x2
, int y2
, int y
)
45 return x1
+ (x2
- x1
) * (y
- y1
) / (y2
- y1
);
48 void GraphicsContext::DrawLine(int x1
, int y1
, int x2
, int y2
)
55 for (int rect
= 0; rect
< fClipRegion
.CountRects(); rect
++) {
56 const Rect
&clipRect
= fClipRegion
.RectAt(rect
);
61 unsigned point1mask
= clipmask(clippedX1
, clippedY1
, clipRect
);
62 unsigned point2mask
= clipmask(clippedX2
, clippedY2
, clipRect
);
64 bool rejected
= false;
65 while (point1mask
!= 0 || point2mask
!= 0) {
66 if ((point1mask
& point2mask
) != 0) {
71 unsigned mask
= point1mask
? point1mask
: point2mask
;
76 x
= horz_intersection(clippedX1
, clippedY1
, clippedX2
, clippedY2
, y
);
77 } else if (mask
& kTop
) {
79 x
= horz_intersection(clippedX1
, clippedY1
, clippedX2
, clippedY2
, y
);
80 } else if (mask
& kRight
) {
82 y
= vert_intersection(clippedX1
, clippedY1
, clippedX2
, clippedY2
, x
);
83 } else if (mask
& kLeft
) {
85 y
= vert_intersection(clippedX1
, clippedY1
, clippedX2
, clippedY2
, x
);
90 point1mask
= clipmask(x
, y
, clipRect
);
95 point2mask
= clipmask(x
, y
, clipRect
);
102 fRenderer
->DrawLine(clippedX1
, clippedY1
, clippedX2
, clippedY2
, fCurrentColor
, CSPACE_RGB888
);
106 void GraphicsContext::FillRect(int x1
, int y1
, int x2
, int y2
)
113 if (x1
> x2
) swap(x1
, x2
);
114 if (y1
> y2
) swap(y1
, y2
);
116 for (int rect
= 0; rect
< fClipRegion
.CountRects(); rect
++) {
117 const Rect
&clipRect
= fClipRegion
.RectAt(rect
);
118 int clipleft
= max(x1
, clipRect
.left
);
119 int cliptop
= max(y1
, clipRect
.top
);
120 int clipright
= min(x2
, clipRect
.right
);
121 int clipbottom
= min(y2
, clipRect
.bottom
);
123 if (clipright
>= clipleft
&& clipbottom
>= cliptop
)
124 fRenderer
->FillRect(clipleft
, cliptop
, clipright
, clipbottom
,
125 fCurrentColor
, CSPACE_RGB888
);
129 void GraphicsContext::Blit(int x
, int y
, color888 image
[], int image_width
,
130 int image_height
, int imageStrideWidth
)
135 for (int rect
= 0; rect
< fClipRegion
.CountRects(); rect
++) {
136 const Rect
&clipRect
= fClipRegion
.RectAt(rect
);
137 int clipleft
= max(x
, clipRect
.left
);
138 int cliptop
= max(y
, clipRect
.top
);
139 int clipright
= min(x
+ image_width
- 1, clipRect
.right
);
140 int clipbottom
= min(y
+ image_height
- 1, clipRect
.bottom
);
142 if (clipright
>= clipleft
&& clipbottom
>= cliptop
) {
143 fRenderer
->Blit(clipleft
, cliptop
, image
+ (clipleft
- x
) +
144 (cliptop
- y
) * imageStrideWidth
, CSPACE_RGB888
, clipright
- clipleft
+ 1,
145 clipbottom
- cliptop
+ 1, imageStrideWidth
);
150 void GraphicsContext::StretchBlit(Rect imageRect
, Rect screenRect
, color888 image
[], int imageStrideWidth
)
152 screenRect
.left
+= fXOrigin
;
153 screenRect
.top
+= fYOrigin
;
154 screenRect
.right
+= fXOrigin
;
155 screenRect
.bottom
+= fYOrigin
;
157 for (int rect
= 0; rect
< fClipRegion
.CountRects(); rect
++) {
158 const Rect
&clipRect
= fClipRegion
.RectAt(rect
);
159 Rect clippedScreenRect
;
160 clippedScreenRect
.left
= max(screenRect
.left
, clipRect
.left
);
161 clippedScreenRect
.top
= max(screenRect
.top
, clipRect
.top
);
162 clippedScreenRect
.right
= min(screenRect
.right
, clipRect
.right
);
163 clippedScreenRect
.bottom
= min(screenRect
.bottom
, clipRect
.bottom
);
165 if (clippedScreenRect
.Width() > 0 && clippedScreenRect
.Height() > 0) {
166 Rect clippedImageRect
;
167 clippedImageRect
.left
= (clippedScreenRect
.left
- screenRect
.left
)
168 * imageRect
.Width() / screenRect
.Width();
169 clippedImageRect
.right
= (clippedScreenRect
.right
- screenRect
.left
)
170 * imageRect
.Width() / screenRect
.Width();
171 clippedImageRect
.top
= (clippedScreenRect
.top
- screenRect
.top
)
172 * imageRect
.Height() / screenRect
.Height();
173 clippedImageRect
.bottom
= (clippedScreenRect
.bottom
- screenRect
.top
)
174 * imageRect
.Height() / screenRect
.Height();
176 fRenderer
->StretchBlit(clippedImageRect
, clippedScreenRect
, image
, CSPACE_RGB888
, imageStrideWidth
);
181 void GraphicsContext::CopyRect(Rect src
, Rect dest
, const Region
&inCleanRegion
,
182 Region
&outNotCopied
)
184 src
.OffsetBy(fXOrigin
, fYOrigin
);
185 dest
.OffsetBy(fXOrigin
, fYOrigin
);
187 int dX
= dest
.left
- src
.left
;
188 int dY
= dest
.top
- src
.top
;
189 Region copyRegion
= inCleanRegion
;
190 copyRegion
.ConstrainTo(dest
);
191 copyRegion
.Translate(-dX
, -dY
);
192 copyRegion
.Intersect(inCleanRegion
);
193 for (int rect
= 0; rect
< copyRegion
.CountRects(); rect
++) {
194 const Rect
&srcRect
= copyRegion
.RectAt(rect
);
195 Rect
destRect(srcRect
);
196 destRect
.OffsetBy(dX
, dY
);
197 fRenderer
->CopyRect(srcRect
, destRect
);
201 copyRegion
.Intersect(fClipRegion
);
202 outNotCopied
= copyRegion
;
205 void GraphicsContext::DrawString(int x
, int y
, const char *string
)
209 const unsigned char *font_ptr
= &font5x8
[*string
* (5*8)];
211 for(int i
= 0; i
< 5*8; i
++) {
213 glyph
[i
] = fCurrentColor
;
215 glyph
[i
] = TRANS888COLOR
;
218 Blit(x
, y
, glyph
, 5, 8, 5);
224 Rect
GraphicsContext::Bounds()
226 Rect rect
= fClipRegion
.Bounds();
227 rect
.OffsetBy(-fXOrigin
, -fYOrigin
);