1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS win32 subsystem 4 * PURPOSE: PATHOBJ service routines 5 * FILE: win32ss/gdi/eng/pathobj.c 6 * PROGRAMERS: Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include <win32k.h> 12 #undef XFORMOBJ 13 14 #define NDEBUG 15 #include <debug.h> 16 17 /* FUNCTIONS *****************************************************************/ 18 19 /* FIXME: set last error */ 20 /* FIXME: PATHOBJ_vEnumStartClipLines and PATHOBJ_bEnumClipLines */ 21 22 /* 23 * @implemented 24 */ 25 PATHOBJ* 26 APIENTRY 27 EngCreatePath(VOID) 28 { 29 PEPATHOBJ pPathObj; 30 const ULONG size = sizeof(EPATHOBJ); 31 32 PPATH pPath = PATH_AllocPathWithHandle(); 33 if (pPath == NULL) 34 { 35 return NULL; 36 } 37 38 pPathObj = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ); 39 if (pPathObj == NULL) 40 { 41 return NULL; 42 } 43 RtlZeroMemory(pPathObj, size); 44 45 pPathObj->pPath = pPath; 46 47 pPath->flType = PATHTYPE_KEEPME; 48 pPath->epo = pPathObj; 49 50 return &pPathObj->po; 51 } 52 53 /* 54 * @implemented 55 */ 56 VOID 57 APIENTRY 58 EngDeletePath(IN PATHOBJ *ppo) 59 { 60 PEPATHOBJ pPathObj; 61 PEXTPATHDATA ppd, ppdNext; 62 PPATH pPath; 63 64 pPathObj = (PEPATHOBJ)ppo; 65 if (pPathObj == NULL || pPathObj->pPath == NULL) 66 return; 67 68 pPath = pPathObj->pPath; 69 70 for (ppd = pPath->ppdFirst; ppd; ppd = ppdNext) 71 { 72 ppdNext = ppd->ppdNext; 73 ExFreePoolWithTag(ppd, GDITAG_PATHOBJ); 74 } 75 ExFreePoolWithTag(pPathObj, GDITAG_PATHOBJ); 76 GDIOBJ_vDeleteObject(&pPath->BaseObject); 77 } 78 79 /* 80 * @implemented 81 */ 82 BOOL 83 APIENTRY 84 PATHOBJ_bCloseFigure(IN PATHOBJ *ppo) 85 { 86 PEXTPATHDATA ppd; 87 PEPATHOBJ pPathObj = (PEPATHOBJ)ppo; 88 if (pPathObj == NULL || pPathObj->pPath == NULL) 89 return FALSE; 90 91 ppd = pPathObj->pPath->ppdLast; 92 if (ppd == NULL) 93 return FALSE; 94 95 ppd->pd.flags |= PD_CLOSEFIGURE | PD_ENDSUBPATH; 96 return TRUE; 97 } 98 99 /* 100 * @implemented 101 */ 102 VOID 103 APIENTRY 104 PATHOBJ_vEnumStart(IN PATHOBJ *ppo) 105 { 106 PEPATHOBJ pPathObj = (PEPATHOBJ)ppo; 107 if (pPathObj == NULL || pPathObj->pPath == NULL) 108 return; 109 110 pPathObj->pPath->ppdCurrent = pPathObj->pPath->ppdFirst; 111 } 112 113 /* 114 * @implemented 115 */ 116 BOOL 117 APIENTRY 118 PATHOBJ_bEnum( 119 IN PATHOBJ *ppo, 120 OUT PATHDATA *ppd) 121 { 122 PEPATHOBJ pPathObj = (PEPATHOBJ)ppo; 123 if (pPathObj == NULL|| pPathObj->pPath == NULL || pPathObj->pPath->ppdCurrent == NULL) 124 return FALSE; 125 126 *ppd = pPathObj->pPath->ppdCurrent->pd; 127 128 pPathObj->pPath->ppdCurrent = pPathObj->pPath->ppdCurrent->ppdNext; 129 return (pPathObj->pPath->ppdCurrent != NULL); 130 } 131 132 /* 133 * @implemented 134 */ 135 BOOL 136 APIENTRY 137 PATHOBJ_bMoveTo( 138 IN PATHOBJ *ppo, 139 IN POINTFIX ptfx) 140 { 141 PEPATHOBJ pPathObj; 142 PEXTPATHDATA ppd, ppdLast; 143 144 pPathObj = (PEPATHOBJ)ppo; 145 if (pPathObj == NULL || pPathObj->pPath == NULL) 146 return FALSE; 147 148 /* allocate a subpath data */ 149 ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ); 150 if (ppd == NULL) 151 return FALSE; 152 153 RtlZeroMemory(ppd, sizeof(EXTPATHDATA)); 154 155 /* add the first point to the subpath */ 156 ppd->pd.flags = PD_BEGINSUBPATH; 157 ppd->pd.count = 1; 158 ppd->pd.pptfx = ExAllocatePoolWithTag(PagedPool, sizeof(POINTFIX), GDITAG_PATHOBJ); 159 if (ppd->pd.pptfx == NULL) 160 { 161 ExFreePoolWithTag(ppd, GDITAG_PATHOBJ); 162 return FALSE; 163 } 164 ppd->pd.pptfx[0] = ptfx; 165 166 ppdLast = pPathObj->pPath->ppdLast; 167 if (ppdLast) 168 { 169 /* end the last subpath */ 170 ppdLast->pd.flags |= PD_ENDSUBPATH; 171 172 /* add the subpath to the last */ 173 ppdLast->ppdNext = ppd; 174 pPathObj->pPath->ppdLast = ppd; 175 } 176 else 177 { 178 /* add the subpath */ 179 pPathObj->pPath->ppdLast = pPathObj->pPath->ppdFirst = ppd; 180 } 181 182 pPathObj->po.cCurves++; 183 184 return TRUE; 185 } 186 187 /* 188 * @implemented 189 */ 190 BOOL 191 APIENTRY 192 PATHOBJ_bPolyLineTo( 193 IN PATHOBJ *ppo, 194 IN POINTFIX *pptfx, 195 IN ULONG cptfx) 196 { 197 PEPATHOBJ pPathObj; 198 PEXTPATHDATA ppd, ppdLast; 199 PPOINTFIX pptfxNew, pptfxOld; 200 ULONG size; 201 202 pPathObj = (PEPATHOBJ)ppo; 203 if (pPathObj == NULL || pPathObj->pPath == NULL || pptfx == NULL || cptfx == 0) 204 return FALSE; 205 206 ppdLast = pPathObj->pPath->ppdLast; 207 if (ppdLast == NULL) 208 { 209 /* allocate a subpath data */ 210 ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ); 211 if (ppd == NULL) 212 return FALSE; 213 214 /* store data */ 215 RtlZeroMemory(ppd, sizeof(EXTPATHDATA)); 216 ppd->pd.flags = PD_BEGINSUBPATH; 217 218 size = cptfx * sizeof(POINTFIX); 219 pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ); 220 if (pptfxNew == NULL) 221 { 222 ExFreePoolWithTag(ppd, GDITAG_PATHOBJ); 223 return FALSE; 224 } 225 RtlCopyMemory(pptfxNew, pptfx, size); 226 ppd->pd.pptfx = pptfxNew; 227 ppd->pd.count = cptfx; 228 229 /* set the subpath */ 230 pPathObj->pPath->ppdLast = pPathObj->pPath->ppdFirst = ppd; 231 232 pPathObj->po.cCurves++; 233 } 234 else if (ppdLast->pd.flags & (PD_BEZIERS | PD_ENDSUBPATH)) 235 { 236 /* allocate a subpath data */ 237 ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ); 238 if (ppd == NULL) 239 return FALSE; 240 241 /* store data */ 242 RtlZeroMemory(ppd, sizeof(EXTPATHDATA)); 243 ppd->pd.flags = 0; 244 ppd->pd.count = cptfx; 245 246 size = cptfx * sizeof(POINTFIX); 247 pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ); 248 if (pptfxNew == NULL) 249 { 250 ExFreePoolWithTag(ppd, GDITAG_PATHOBJ); 251 return FALSE; 252 } 253 RtlCopyMemory(pptfxNew, pptfx, size); 254 ppd->pd.pptfx = pptfxNew; 255 256 /* add to last */ 257 ppdLast->ppdNext = ppd; 258 pPathObj->pPath->ppdLast = ppd; 259 260 pPathObj->po.cCurves++; 261 } 262 else 263 { 264 /* concatenate ppdLast->pd.pptfx and pptfx */ 265 size = (ppdLast->pd.count + cptfx) * sizeof(POINTFIX); 266 pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ); 267 if (pptfxNew == NULL) 268 return FALSE; 269 270 size = ppdLast->pd.count * sizeof(POINTFIX); 271 RtlCopyMemory(&pptfxNew[0], ppdLast->pd.pptfx, size); 272 size = cptfx * sizeof(POINTFIX); 273 RtlCopyMemory(&pptfxNew[ppdLast->pd.count], pptfx, size); 274 275 pptfxOld = ppdLast->pd.pptfx; 276 ppdLast->pd.pptfx = pptfxNew; 277 ppdLast->pd.count += cptfx; 278 ExFreePoolWithTag(pptfxOld, GDITAG_PATHOBJ); 279 } 280 281 return TRUE; 282 } 283 284 /* 285 * @implemented 286 */ 287 BOOL 288 APIENTRY 289 PATHOBJ_bPolyBezierTo( 290 IN PATHOBJ *ppo, 291 IN POINTFIX *pptfx, 292 IN ULONG cptfx) 293 { 294 PEPATHOBJ pPathObj; 295 PEXTPATHDATA ppd, ppdLast; 296 PPOINTFIX pptfxNew, pptfxOld; 297 ULONG size; 298 299 pPathObj = (PEPATHOBJ)ppo; 300 if (pPathObj == NULL || pPathObj->pPath == NULL || pptfx == NULL || cptfx == 0) 301 return FALSE; 302 303 ppdLast = pPathObj->pPath->ppdLast; 304 if (ppdLast == NULL) 305 { 306 /* allocate a subpath data */ 307 ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ); 308 if (ppd == NULL) 309 return FALSE; 310 311 /* store data */ 312 RtlZeroMemory(ppd, sizeof(EXTPATHDATA)); 313 ppd->pd.flags = PD_BEGINSUBPATH | PD_BEZIERS; 314 315 size = cptfx * sizeof(POINTFIX); 316 pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ); 317 if (pptfxNew == NULL) 318 { 319 ExFreePoolWithTag(ppd, GDITAG_PATHOBJ); 320 return FALSE; 321 } 322 RtlCopyMemory(pptfxNew, pptfx, size); 323 ppd->pd.pptfx = pptfxNew; 324 ppd->pd.count = cptfx; 325 326 /* set the subpath */ 327 pPathObj->pPath->ppdLast = pPathObj->pPath->ppdFirst = ppd; 328 329 pPathObj->po.cCurves++; 330 } 331 else if (!(ppdLast->pd.flags & PD_BEZIERS) || (ppdLast->pd.flags & PD_ENDSUBPATH)) 332 { 333 /* allocate a subpath data */ 334 ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ); 335 if (ppd == NULL) 336 return FALSE; 337 338 /* store data */ 339 RtlZeroMemory(ppd, sizeof(EXTPATHDATA)); 340 ppd->pd.flags = PD_BEZIERS; 341 ppd->pd.count = cptfx; 342 343 size = cptfx * sizeof(POINTFIX); 344 pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ); 345 if (pptfxNew == NULL) 346 { 347 ExFreePoolWithTag(ppd, GDITAG_PATHOBJ); 348 return FALSE; 349 } 350 RtlCopyMemory(pptfxNew, pptfx, size); 351 ppd->pd.pptfx = pptfxNew; 352 353 /* add to last */ 354 ppdLast->ppdNext = ppd; 355 pPathObj->pPath->ppdLast = ppd; 356 357 pPathObj->po.cCurves++; 358 } 359 else 360 { 361 /* concatenate ppdLast->pd.pptfx and pptfx */ 362 size = (ppdLast->pd.count + cptfx) * sizeof(POINTFIX); 363 pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ); 364 if (pptfxNew == NULL) 365 return FALSE; 366 367 size = ppdLast->pd.count * sizeof(POINTFIX); 368 RtlCopyMemory(&pptfxNew[0], ppdLast->pd.pptfx, size); 369 size = cptfx * sizeof(POINTFIX); 370 RtlCopyMemory(&pptfxNew[ppdLast->pd.count], pptfx, size); 371 372 pptfxOld = ppdLast->pd.pptfx; 373 ppdLast->pd.pptfx = pptfxNew; 374 ppdLast->pd.count += cptfx; 375 ExFreePoolWithTag(pptfxOld, GDITAG_PATHOBJ); 376 } 377 378 pPathObj->po.fl |= PO_BEZIERS; 379 380 return TRUE; 381 } 382 383 VOID 384 APIENTRY 385 PATHOBJ_vEnumStartClipLines( 386 IN PATHOBJ *ppo, 387 IN CLIPOBJ *pco, 388 IN SURFOBJ *pso, 389 IN LINEATTRS *pla) 390 { 391 UNIMPLEMENTED; 392 } 393 394 BOOL 395 APIENTRY 396 PATHOBJ_bEnumClipLines( 397 IN PATHOBJ *ppo, 398 IN ULONG cb, 399 OUT CLIPLINE *pcl) 400 { 401 UNIMPLEMENTED; 402 return FALSE; 403 } 404 405 /* 406 * @implemented 407 */ 408 VOID 409 APIENTRY 410 PATHOBJ_vGetBounds( 411 IN PATHOBJ *ppo, 412 OUT PRECTFX prectfx) 413 { 414 FIX xLeft, yTop, xRight, yBottom; 415 PEPATHOBJ pPathObj; 416 PEXTPATHDATA ppd, ppdNext; 417 ULONG i; 418 419 pPathObj = (PEPATHOBJ)ppo; 420 if (pPathObj == NULL || pPathObj->pPath == NULL || prectfx == NULL) 421 return; 422 423 yTop = xLeft = MAXLONG; 424 yBottom = xRight = MINLONG; 425 426 for (ppd = pPathObj->pPath->ppdFirst; ppd; ppd = ppdNext) 427 { 428 ppdNext = ppd->ppdNext; 429 for (i = 0; i < ppd->pd.count; ++i) 430 { 431 PPOINTFIX pptfx = &ppd->pd.pptfx[i]; 432 if (pptfx->x < xLeft) 433 xLeft = pptfx->x; 434 if (pptfx->x > xRight) 435 xRight = pptfx->x; 436 if (pptfx->y < yTop) 437 yTop = pptfx->y; 438 if (pptfx->y > yBottom) 439 yBottom = pptfx->y; 440 } 441 } 442 443 if (xLeft <= xRight && yTop <= yBottom) 444 { 445 prectfx->xLeft = xLeft; 446 prectfx->yTop = yTop; 447 prectfx->xRight = xRight + 1; 448 prectfx->yBottom = yBottom + 1; 449 } 450 else 451 { 452 RtlZeroMemory(prectfx, sizeof(*prectfx)); 453 } 454 } 455 456 /* EOF */ 457