| 191 | } |
| 192 | } |
| 193 | void CanvasDrawLineAA(double x1, double y1, double x2, double y2, Canvas* ptr) |
| 194 | { |
| 195 | if(!ptr) |
| 196 | { |
| 197 | nullcThrowError("ERROR: Canvas object is nullptr"); |
| 198 | return; |
| 199 | } |
| 200 | double dx = x2 - x1; |
| 201 | double dy = y2 - y1; |
| 202 | bool steep = false; |
| 203 | if(abs(dx) < abs(dy)) |
| 204 | { |
| 205 | swap(x1, y1); |
| 206 | swap(x2, y2); |
| 207 | swap(dx, dy); |
| 208 | steep = true; |
| 209 | } |
| 210 | if(x2 < x1) |
| 211 | { |
| 212 | swap(x1, x2); |
| 213 | swap(y1, y2); |
| 214 | } |
| 215 | if(x1 < 0.0) |
| 216 | { |
| 217 | if(x2 < 0.0) |
| 218 | return; |
| 219 | double l = -x1 / (x2 - x1); |
| 220 | x1 = 0.0; |
| 221 | y1 = y1 * (1.0 - l) + y2 * l; |
| 222 | } |
| 223 | if(x1 > (steep ? ptr->height : ptr->width)) |
| 224 | return; |
| 225 | if(x2 > (steep ? ptr->height : ptr->width)) |
| 226 | x2 = steep ? ptr->height : ptr->width; |
| 227 | double gradient = dy / dx; |
| 228 | |
| 229 | // handle first endpoint |
| 230 | int xend = round(x1); |
| 231 | double yend = y1 + gradient * (xend - x1); |
| 232 | double xgap = rfpart(x1 + 0.5); |
| 233 | int xpxl1 = xend; |
| 234 | int ypxl1 = int(yend); |
| 235 | if(steep) |
| 236 | { |
| 237 | CanvasDrawPointInternal(ypxl1, xpxl1, rfpart(yend) * xgap, ptr); |
| 238 | CanvasDrawPointInternal(ypxl1 + 1, xpxl1, fpart(yend) * xgap, ptr); |
| 239 | }else{ |
| 240 | CanvasDrawPointInternal(xpxl1, ypxl1, rfpart(yend) * xgap, ptr); |
| 241 | CanvasDrawPointInternal(xpxl1, ypxl1 + 1, fpart(yend) * xgap, ptr); |
| 242 | } |
| 243 | double intery = yend + gradient; // first y-intersection for the main loop |
| 244 | |
| 245 | // handle second endpoint |
| 246 | xend = round(x2); |
| 247 | yend = y2 + gradient * (xend - x2); |
| 248 | xgap = fpart(x2 + 0.5); |
| 249 | int xpxl2 = xend ; // this will be used in the main loop |
| 250 | int ypxl2 = int(yend); |
no test coverage detected