1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS System Libraries 4 * FILE: win32ss/gdi/gdi32/objects/coord.c 5 * PURPOSE: Functions for coordinate transformation 6 * PROGRAMMER: 7 */ 8 #include <precomp.h> 9 10 /* Currently we use a MATRIX inside the DC_ATTR containing the 11 coordinate transformations, while we deal with XFORM structures 12 internally. If we move all coordinate transformation to gdi32, 13 we might as well have an XFORM structure in the DC_ATTR. */ 14 void 15 MatrixToXForm(XFORM *pxform, const MATRIX *pmx) 16 { 17 XFORML *pxforml = (XFORML*)pxform; 18 pxforml->eM11 = FOtoF(&pmx->efM11); 19 pxforml->eM12 = FOtoF(&pmx->efM12); 20 pxforml->eM21 = FOtoF(&pmx->efM21); 21 pxforml->eM22 = FOtoF(&pmx->efM22); 22 pxforml->eDx = FOtoF(&pmx->efDx); 23 pxforml->eDy = FOtoF(&pmx->efDy); 24 } 25 26 void 27 GdiTransformPoints2( 28 _In_ XFORM *pxform, 29 _Out_writes_(nCount) PPOINT pptOut, 30 _In_reads_(nCount) PPOINT pptIn, 31 _In_ ULONG nCount) 32 { 33 ULONG i; 34 FLOAT x, y; 35 36 for (i = 0; i < nCount; i++) 37 { 38 x = pptIn[i].x * pxform->eM11 + pptIn[i].y * pxform->eM12 + pxform->eDx; 39 pptOut[i].x = _lrintf(x); 40 y = pptIn[i].x * pxform->eM21 + pptIn[i].y * pxform->eM22 + pxform->eDy; 41 pptOut[i].y = _lrintf(y); 42 } 43 } 44 45 FORCEINLINE 46 void 47 GdiTransformPoints( 48 _In_ MATRIX *pmx, 49 _Out_writes_(nCount) PPOINT pptOut, 50 _In_reads_(nCount) PPOINT pptIn, 51 _In_ ULONG nCount) 52 { 53 XFORM xform; 54 55 MatrixToXForm(&xform, pmx); 56 GdiTransformPoints2(&xform, pptOut, pptIn, nCount); 57 } 58 59 #define MAX_OFFSET 4294967041.0 60 #define _fmul(x,y) (((x) == 0) ? 0 : (x) * (y)) 61 62 BOOL 63 WINAPI 64 CombineTransform( 65 _Out_ LPXFORM pxfResult, 66 _In_ const XFORM *pxf1, 67 _In_ const XFORM *pxf2) 68 { 69 XFORM xformTmp; 70 71 /* Check paramters */ 72 if (!pxfResult || !pxf1 || !pxf2) return FALSE; 73 74 /* Do matrix multiplication, start with scaling elements */ 75 xformTmp.eM11 = (pxf1->eM11 * pxf2->eM11) + (pxf1->eM12 * pxf2->eM21); 76 xformTmp.eM22 = (pxf1->eM21 * pxf2->eM12) + (pxf1->eM22 * pxf2->eM22); 77 78 /* Calculate shear/rotate elements only of they are present */ 79 if ((pxf1->eM12 != 0.) || (pxf1->eM21 != 0.) || 80 (pxf2->eM12 != 0.) || (pxf2->eM21 != 0.)) 81 { 82 xformTmp.eM12 = (pxf1->eM11 * pxf2->eM12) + (pxf1->eM12 * pxf2->eM22); 83 xformTmp.eM21 = (pxf1->eM21 * pxf2->eM11) + (pxf1->eM22 * pxf2->eM21); 84 } 85 else 86 { 87 xformTmp.eM12 = 0.; 88 xformTmp.eM21 = 0.; 89 } 90 91 /* Calculate the offset */ 92 xformTmp.eDx = _fmul(pxf1->eDx, pxf2->eM11) + _fmul(pxf1->eDy, pxf2->eM21) + pxf2->eDx; 93 xformTmp.eDy = _fmul(pxf1->eDx, pxf2->eM12) + _fmul(pxf1->eDy, pxf2->eM22) + pxf2->eDy; 94 95 /* Check for invalid offset ranges */ 96 if ((xformTmp.eDx > MAX_OFFSET) || (xformTmp.eDx < -MAX_OFFSET) || 97 (xformTmp.eDy > MAX_OFFSET) || (xformTmp.eDy < -MAX_OFFSET)) 98 { 99 return FALSE; 100 } 101 102 /* All is ok, return the calculated values */ 103 *pxfResult = xformTmp; 104 return TRUE; 105 } 106 107 108 /* 109 * @implemented 110 * 111 */ 112 int 113 WINAPI 114 GetMapMode( 115 _In_ HDC hdc) 116 { 117 PDC_ATTR pdcattr; 118 119 /* Get the DC attribute */ 120 pdcattr = GdiGetDcAttr(hdc); 121 if (pdcattr == NULL) 122 { 123 SetLastError(ERROR_INVALID_PARAMETER); 124 return 0; 125 } 126 127 /* Return the map mode */ 128 return pdcattr->iMapMode; 129 } 130 131 /* 132 * @implemented 133 */ 134 INT 135 WINAPI 136 SetMapMode( 137 _In_ HDC hdc, 138 _In_ INT iMode) 139 { 140 PDC_ATTR pdcattr; 141 142 /* Handle METADC16 here, since we don't have a DCATTR. */ 143 if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) \ 144 { 145 return METADC_SetMapMode(hdc, iMode); 146 } 147 148 /* Get the DC attribute */ 149 pdcattr = GdiGetDcAttr(hdc); 150 if (pdcattr == NULL) 151 { 152 SetLastError(ERROR_INVALID_PARAMETER); 153 return 0; 154 } 155 156 /* Force change if Isotropic is set for recompute. */ 157 if ((iMode != pdcattr->iMapMode) || (iMode == MM_ISOTROPIC)) 158 { 159 pdcattr->ulDirty_ &= ~SLOW_WIDTHS; 160 return GetAndSetDCDWord(hdc, GdiGetSetMapMode, iMode, EMR_SETMAPMODE, 0, 0 ); 161 } 162 163 return pdcattr->iMapMode; 164 } 165 166 167 BOOL 168 WINAPI 169 DPtoLP( 170 _In_ HDC hdc, 171 _Inout_updates_(nCount) LPPOINT lpPoints, 172 _In_ INT nCount) 173 { 174 PDC_ATTR pdcattr; 175 SIZEL sizlView; 176 177 if (nCount <= 0) 178 return TRUE; 179 180 if (hdc == NULL) 181 { 182 SetLastError(ERROR_INVALID_PARAMETER); 183 return FALSE; 184 } 185 if (lpPoints == NULL) 186 { 187 return TRUE; 188 } 189 190 pdcattr = GdiGetDcAttr(hdc); 191 if (pdcattr == NULL) 192 return FALSE; 193 194 if (pdcattr->iMapMode == MM_ISOTROPIC) 195 { 196 if (NtGdiGetDCPoint(hdc, GdiGetViewPortExt, (PPOINTL)&sizlView)) 197 { 198 if (sizlView.cx == 0 || sizlView.cy == 0) 199 return FALSE; 200 } 201 } 202 203 return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiDpToLp); 204 } 205 206 BOOL 207 WINAPI 208 LPtoDP( 209 _In_ HDC hdc, 210 _Inout_updates_(nCount) LPPOINT lpPoints, 211 _In_ INT nCount) 212 { 213 PDC_ATTR pdcattr; 214 215 if (nCount <= 0) 216 return TRUE; 217 218 if (hdc == NULL) 219 { 220 SetLastError(ERROR_INVALID_PARAMETER); 221 return FALSE; 222 } 223 if (lpPoints == NULL) 224 { 225 return TRUE; 226 } 227 228 pdcattr = GdiGetDcAttr(hdc); 229 if (pdcattr == NULL) 230 return FALSE; 231 232 return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiLpToDp); 233 } 234 235 /* 236 * @implemented 237 * 238 */ 239 BOOL 240 WINAPI 241 GetCurrentPositionEx( 242 _In_ HDC hdc, 243 _Out_ LPPOINT lpPoint) 244 { 245 PDC_ATTR pdcattr; 246 247 /* Get the DC attribute */ 248 pdcattr = GdiGetDcAttr(hdc); 249 if ((pdcattr == NULL) || (lpPoint == NULL)) 250 { 251 SetLastError(ERROR_INVALID_PARAMETER); 252 return FALSE; 253 } 254 255 if (pdcattr->ulDirty_ & DIRTY_PTLCURRENT) // have a hit! 256 { 257 lpPoint->x = pdcattr->ptfxCurrent.x; 258 lpPoint->y = pdcattr->ptfxCurrent.y; 259 DPtoLP(hdc, lpPoint, 1); // reconvert back. 260 pdcattr->ptlCurrent.x = lpPoint->x; // save it 261 pdcattr->ptlCurrent.y = lpPoint->y; 262 pdcattr->ulDirty_ &= ~DIRTY_PTLCURRENT; // clear bit 263 } 264 else 265 { 266 lpPoint->x = pdcattr->ptlCurrent.x; 267 lpPoint->y = pdcattr->ptlCurrent.y; 268 } 269 270 return TRUE; 271 } 272 273 /* 274 * @implemented 275 */ 276 BOOL 277 WINAPI 278 GetWorldTransform( 279 _In_ HDC hdc, 280 _Out_ LPXFORM pxform) 281 { 282 PDC_ATTR pdcattr; 283 284 pdcattr = GdiGetDcAttr(hdc); 285 if (!pdcattr) 286 { 287 SetLastError(ERROR_INVALID_HANDLE); 288 return FALSE; 289 } 290 #if 0 291 if (pdcattr->flXform & ANY_XFORM_INVALID) 292 { 293 GdiFixupTransforms(pdcattr); 294 } 295 296 MatrixToXForm(pxform, &pdcattr->mxWorldToDevice); 297 #endif 298 return NtGdiGetTransform(hdc, GdiWorldSpaceToPageSpace, pxform); 299 } 300 301 302 BOOL 303 WINAPI 304 SetWorldTransform( 305 _In_ HDC hdc, 306 _Out_ CONST XFORM *pxform) 307 { 308 return ModifyWorldTransform(hdc, pxform, MWT_SET); 309 } 310 311 312 BOOL 313 WINAPI 314 ModifyWorldTransform( 315 _In_ HDC hdc, 316 _In_opt_ CONST XFORM *pxform, 317 _In_ DWORD dwMode) 318 { 319 PDC_ATTR pdcattr; 320 321 if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) 322 return FALSE; 323 324 if (dwMode == MWT_SET) 325 { 326 HANDLE_EMETAFDC(BOOL, SetWorldTransform, FALSE, hdc, pxform); 327 } 328 else 329 { 330 HANDLE_EMETAFDC(BOOL, ModifyWorldTransform, FALSE, hdc, pxform, dwMode); 331 } 332 333 /* Get the DC attribute */ 334 pdcattr = GdiGetDcAttr(hdc); 335 if (pdcattr == NULL) 336 { 337 SetLastError(ERROR_INVALID_PARAMETER); 338 return FALSE; 339 } 340 341 /* Check that graphics mode is GM_ADVANCED */ 342 if (pdcattr->iGraphicsMode != GM_ADVANCED) 343 return FALSE; 344 345 /* Call win32k to do the work */ 346 return NtGdiModifyWorldTransform(hdc, (LPXFORM)pxform, dwMode); 347 } 348 349 BOOL 350 WINAPI 351 GetViewportExtEx( 352 _In_ HDC hdc, 353 _Out_ LPSIZE lpSize) 354 { 355 PDC_ATTR pdcattr; 356 357 /* Get the DC attribute */ 358 pdcattr = GdiGetDcAttr(hdc); 359 if (pdcattr == NULL) 360 { 361 /* Do not set LastError here! */ 362 return FALSE; 363 } 364 365 /* Check if we need to update values */ 366 if ((pdcattr->flXform & PAGE_EXTENTS_CHANGED) && 367 (pdcattr->iMapMode == MM_ISOTROPIC)) 368 { 369 /* Call win32k to do the work */ 370 return NtGdiGetDCPoint(hdc, GdiGetViewPortExt, (PPOINTL)lpSize); 371 } 372 373 /* Nothing to calculate, return the current extension */ 374 lpSize->cx = pdcattr->szlViewportExt.cx; 375 lpSize->cy = pdcattr->szlViewportExt.cy; 376 377 return TRUE; 378 } 379 380 381 BOOL 382 WINAPI 383 GetViewportOrgEx( 384 _In_ HDC hdc, 385 _Out_ LPPOINT lpPoint) 386 { 387 PDC_ATTR pdcattr; 388 389 /* Get the DC attribute */ 390 pdcattr = GdiGetDcAttr(hdc); 391 if (pdcattr == NULL) 392 { 393 /* Do not set LastError here! */ 394 return FALSE; 395 } 396 397 /* Get the current viewport org */ 398 lpPoint->x = pdcattr->ptlViewportOrg.x; 399 lpPoint->y = pdcattr->ptlViewportOrg.y; 400 401 /* Handle right-to-left layout */ 402 if (pdcattr->dwLayout & LAYOUT_RTL) 403 lpPoint->x = -lpPoint->x; 404 405 return TRUE; 406 } 407 408 409 BOOL 410 WINAPI 411 GetWindowExtEx( 412 _In_ HDC hdc, 413 _Out_ LPSIZE lpSize) 414 { 415 PDC_ATTR pdcattr; 416 417 /* Get the DC attribute */ 418 pdcattr = GdiGetDcAttr(hdc); 419 if (pdcattr == NULL) 420 { 421 /* Do not set LastError here! */ 422 return FALSE; 423 } 424 425 /* Get the current window extension */ 426 lpSize->cx = pdcattr->szlWindowExt.cx; 427 lpSize->cy = pdcattr->szlWindowExt.cy; 428 429 /* Handle right-to-left layout */ 430 if (pdcattr->dwLayout & LAYOUT_RTL) 431 lpSize->cx = -lpSize->cx; 432 433 return TRUE; 434 } 435 436 437 BOOL 438 WINAPI 439 GetWindowOrgEx( 440 _In_ HDC hdc, 441 _Out_ LPPOINT lpPoint) 442 { 443 PDC_ATTR pdcattr; 444 445 /* Get the DC attribute */ 446 pdcattr = GdiGetDcAttr(hdc); 447 if (pdcattr == NULL) 448 { 449 /* Do not set LastError here! */ 450 return FALSE; 451 } 452 453 /* Get the current window origin */ 454 lpPoint->x = pdcattr->ptlWindowOrg.x; 455 lpPoint->y = pdcattr->ptlWindowOrg.y; 456 457 return TRUE; 458 } 459 460 /* 461 * @implemented 462 */ 463 BOOL 464 WINAPI 465 SetViewportExtEx( 466 _In_ HDC hdc, 467 _In_ int nXExtent, 468 _In_ int nYExtent, 469 _Out_opt_ LPSIZE lpSize) 470 { 471 PDC_ATTR pdcattr; 472 473 HANDLE_METADC(BOOL, SetViewportExtEx, FALSE, hdc, nXExtent, nYExtent); 474 475 /* Get the DC attribute */ 476 pdcattr = GdiGetDcAttr(hdc); 477 if (pdcattr == NULL) 478 { 479 SetLastError(ERROR_INVALID_PARAMETER); 480 return FALSE; 481 } 482 483 /* Check if the caller wants the old extension */ 484 if (lpSize) 485 { 486 /* Return the current viewport extension */ 487 lpSize->cx = pdcattr->szlViewportExt.cx; 488 lpSize->cy = pdcattr->szlViewportExt.cy; 489 } 490 491 /* Check for trivial case */ 492 if ((pdcattr->szlViewportExt.cx == nXExtent) && 493 (pdcattr->szlViewportExt.cy == nYExtent)) 494 return TRUE; 495 496 if (nXExtent == 0 || nYExtent == 0) 497 return TRUE; 498 499 /* Only change viewport extension if we are in iso or aniso mode */ 500 if ((pdcattr->iMapMode == MM_ISOTROPIC) || 501 (pdcattr->iMapMode == MM_ANISOTROPIC)) 502 { 503 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc) 504 { 505 if (pdcattr->ulDirty_ & DC_MODE_DIRTY) 506 { 507 NtGdiFlush(); // Sync up pdcattr from Kernel space. 508 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY; 509 } 510 } 511 512 /* Set the new viewport extension */ 513 pdcattr->szlViewportExt.cx = nXExtent; 514 pdcattr->szlViewportExt.cy = nYExtent; 515 516 /* Handle right-to-left layout */ 517 if (pdcattr->dwLayout & LAYOUT_RTL) 518 NtGdiMirrorWindowOrg(hdc); 519 520 /* Update xform flags */ 521 pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID); 522 } 523 524 return TRUE; 525 } 526 527 /* 528 * @implemented 529 */ 530 BOOL 531 WINAPI 532 SetWindowOrgEx( 533 _In_ HDC hdc, 534 _In_ int X, 535 _In_ int Y, 536 _Out_opt_ LPPOINT lpPoint) 537 { 538 PDC_ATTR pdcattr; 539 540 HANDLE_METADC(BOOL, SetWindowOrgEx, FALSE, hdc, X, Y); 541 542 /* Get the DC attribute */ 543 pdcattr = GdiGetDcAttr(hdc); 544 if (pdcattr == NULL) 545 { 546 /* Do not set LastError here! */ 547 return FALSE; 548 } 549 550 if (lpPoint) 551 { 552 lpPoint->x = pdcattr->ptlWindowOrg.x; 553 lpPoint->y = pdcattr->ptlWindowOrg.y; 554 } 555 556 if ((pdcattr->ptlWindowOrg.x == X) && (pdcattr->ptlWindowOrg.y == Y)) 557 return TRUE; 558 559 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc) 560 { 561 if (pdcattr->ulDirty_ & DC_MODE_DIRTY) 562 { 563 NtGdiFlush(); // Sync up pdcattr from Kernel space. 564 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY; 565 } 566 } 567 568 pdcattr->ptlWindowOrg.x = X; 569 pdcattr->ptlWindowOrg.y = Y; 570 571 pdcattr->lWindowOrgx = X; 572 if (pdcattr->dwLayout & LAYOUT_RTL) NtGdiMirrorWindowOrg(hdc); 573 pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID); 574 return TRUE; 575 576 // return NtGdiSetWindowOrgEx(hdc, X, Y, lpPoint); 577 } 578 579 /* 580 * @implemented 581 */ 582 BOOL 583 WINAPI 584 SetWindowExtEx( 585 _In_ HDC hdc, 586 _In_ INT nXExtent, 587 _In_ INT nYExtent, 588 _Out_opt_ LPSIZE lpSize) 589 { 590 PDC_ATTR pdcattr; 591 592 HANDLE_METADC(BOOL, SetWindowExtEx, FALSE, hdc, nXExtent, nYExtent); 593 594 /* Get the DC attr */ 595 pdcattr = GdiGetDcAttr(hdc); 596 if (!pdcattr) 597 { 598 /* Set the error value and return failure */ 599 SetLastError(ERROR_INVALID_PARAMETER); 600 return FALSE; 601 } 602 603 /* Check if the caller wants the old extension */ 604 if (lpSize) 605 { 606 /* Return the current window extension */ 607 lpSize->cx = pdcattr->szlWindowExt.cx; 608 lpSize->cy = pdcattr->szlWindowExt.cy; 609 610 /* Handle right-to-left layout */ 611 if (pdcattr->dwLayout & LAYOUT_RTL) 612 lpSize->cx = -lpSize->cx; 613 } 614 615 if (pdcattr->dwLayout & LAYOUT_RTL) 616 { 617 NtGdiMirrorWindowOrg(hdc); 618 pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID); 619 } 620 else if ((pdcattr->iMapMode == MM_ISOTROPIC) || 621 (pdcattr->iMapMode == MM_ANISOTROPIC)) 622 { 623 if ((pdcattr->szlWindowExt.cx == nXExtent) && 624 (pdcattr->szlWindowExt.cy == nYExtent)) 625 return TRUE; 626 627 if ((!nXExtent) || (!nYExtent)) 628 return FALSE; 629 630 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc) 631 { 632 if (pdcattr->ulDirty_ & DC_MODE_DIRTY) 633 { 634 NtGdiFlush(); // Sync up Dc_Attr from Kernel space. 635 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY; 636 } 637 } 638 639 pdcattr->szlWindowExt.cx = nXExtent; 640 pdcattr->szlWindowExt.cy = nYExtent; 641 if (pdcattr->dwLayout & LAYOUT_RTL) 642 NtGdiMirrorWindowOrg(hdc); 643 644 pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID); 645 } 646 647 return TRUE; 648 } 649 650 /* 651 * @implemented 652 */ 653 BOOL 654 WINAPI 655 SetViewportOrgEx( 656 _In_ HDC hdc, 657 _In_ int X, 658 _In_ int Y, 659 _Out_opt_ LPPOINT lpPoint) 660 { 661 PDC_ATTR pdcattr; 662 663 HANDLE_METADC(BOOL, SetViewportOrgEx, FALSE, hdc, X, Y); 664 665 /* Get the DC attribute */ 666 pdcattr = GdiGetDcAttr(hdc); 667 if (!pdcattr) 668 { 669 /* Do not set LastError here! */ 670 return FALSE; 671 } 672 //// HACK : XP+ doesn't do this. See CORE-16656 & CORE-16644. 673 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc) 674 { 675 if (pdcattr->ulDirty_ & DC_MODE_DIRTY) 676 { 677 NtGdiFlush(); 678 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY; 679 } 680 } 681 //// 682 if (lpPoint) 683 { 684 lpPoint->x = pdcattr->ptlViewportOrg.x; 685 lpPoint->y = pdcattr->ptlViewportOrg.y; 686 if (pdcattr->dwLayout & LAYOUT_RTL) lpPoint->x = -lpPoint->x; 687 } 688 pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID); 689 if (pdcattr->dwLayout & LAYOUT_RTL) X = -X; 690 pdcattr->ptlViewportOrg.x = X; 691 pdcattr->ptlViewportOrg.y = Y; 692 return TRUE; 693 694 // return NtGdiSetViewportOrgEx(hdc,X,Y,lpPoint); 695 } 696 697 /* 698 * @implemented 699 */ 700 BOOL 701 WINAPI 702 ScaleViewportExtEx( 703 _In_ HDC hdc, 704 _In_ INT xNum, 705 _In_ INT xDenom, 706 _In_ INT yNum, 707 _In_ INT yDenom, 708 _Out_ LPSIZE lpSize) 709 { 710 HANDLE_METADC(BOOL, ScaleViewportExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom); 711 712 if (!GdiGetDcAttr(hdc)) 713 { 714 SetLastError(ERROR_INVALID_PARAMETER); 715 return FALSE; 716 } 717 718 return NtGdiScaleViewportExtEx(hdc, xNum, xDenom, yNum, yDenom, lpSize); 719 } 720 721 /* 722 * @implemented 723 */ 724 BOOL 725 WINAPI 726 ScaleWindowExtEx( 727 _In_ HDC hdc, 728 _In_ INT xNum, 729 _In_ INT xDenom, 730 _In_ INT yNum, 731 _In_ INT yDenom, 732 _Out_ LPSIZE lpSize) 733 { 734 HANDLE_METADC(BOOL, ScaleWindowExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom); 735 736 if (!GdiGetDcAttr(hdc)) 737 { 738 SetLastError(ERROR_INVALID_PARAMETER); 739 return FALSE; 740 } 741 742 return NtGdiScaleWindowExtEx(hdc, xNum, xDenom, yNum, yDenom, lpSize); 743 } 744 745 /* 746 * @implemented 747 */ 748 DWORD 749 WINAPI 750 GetLayout( 751 _In_ HDC hdc) 752 { 753 PDC_ATTR pdcattr; 754 755 /* METADC16 is not supported in this API */ 756 if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) 757 { 758 return GDI_ERROR; 759 } 760 761 /* Get the DC attribute */ 762 pdcattr = GdiGetDcAttr(hdc); 763 if (!pdcattr) 764 { 765 /* Set the error value and return failure */ 766 SetLastError(ERROR_INVALID_PARAMETER); 767 return GDI_ERROR; 768 } 769 770 /* Return the layout */ 771 return pdcattr->dwLayout; 772 } 773 774 775 /* 776 * @implemented 777 */ 778 DWORD 779 WINAPI 780 SetLayout( 781 _In_ HDC hdc, 782 _In_ DWORD dwLayout) 783 { 784 HANDLE_METADC(DWORD, SetLayout, GDI_ERROR, hdc, dwLayout); 785 786 if (!GdiGetDcAttr(hdc)) 787 { 788 SetLastError(ERROR_INVALID_PARAMETER); 789 return GDI_ERROR; 790 } 791 792 return NtGdiSetLayout(hdc, -1, dwLayout); 793 } 794 795 /* 796 * @implemented 797 */ 798 DWORD 799 WINAPI 800 SetLayoutWidth( 801 _In_ HDC hdc, 802 _In_ LONG wox, 803 _In_ DWORD dwLayout) 804 { 805 /* Only normal DCs are handled here */ 806 if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) 807 { 808 return GDI_ERROR; 809 } 810 811 if (!GdiGetDcAttr(hdc)) 812 { 813 SetLastError(ERROR_INVALID_PARAMETER); 814 return GDI_ERROR; 815 } 816 817 return NtGdiSetLayout(hdc, wox, dwLayout); 818 } 819 820 /* 821 * @implemented 822 */ 823 BOOL 824 WINAPI 825 GetDCOrgEx( 826 _In_ HDC hdc, 827 _Out_ LPPOINT lpPoint) 828 { 829 return NtGdiGetDCPoint(hdc, GdiGetDCOrg, (PPOINTL)lpPoint); 830 } 831 832 833 /* 834 * @implemented 835 */ 836 LONG 837 WINAPI 838 GetDCOrg( 839 _In_ HDC hdc) 840 { 841 POINT pt; 842 843 /* Call the new API */ 844 if (!GetDCOrgEx(hdc, &pt)) 845 return 0; 846 847 /* Return the point in the old way */ 848 return(MAKELONG(pt.x, pt.y)); 849 } 850 851 852 /* 853 * @implemented 854 * 855 */ 856 BOOL 857 WINAPI 858 OffsetViewportOrgEx( 859 _In_ HDC hdc, 860 _In_ int nXOffset, 861 _In_ int nYOffset, 862 _Out_opt_ LPPOINT lpPoint) 863 { 864 PDC_ATTR pdcattr; 865 866 HANDLE_METADC16(BOOL, OffsetViewportOrgEx, FALSE, hdc, nXOffset, nYOffset); 867 868 /* Get the DC attribute */ 869 pdcattr = GdiGetDcAttr(hdc); 870 if (!pdcattr) 871 { 872 /* Do not set LastError here! */ 873 return FALSE; 874 } 875 876 if (lpPoint) 877 { 878 *lpPoint = pdcattr->ptlViewportOrg; 879 if ( pdcattr->dwLayout & LAYOUT_RTL) lpPoint->x = -lpPoint->x; 880 } 881 882 if ( nXOffset || nYOffset != nXOffset ) 883 { 884 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc) 885 { 886 if (pdcattr->ulDirty_ & DC_MODE_DIRTY) 887 { 888 NtGdiFlush(); 889 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY; 890 } 891 } 892 893 pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID); 894 if (pdcattr->dwLayout & LAYOUT_RTL) nXOffset = -nXOffset; 895 pdcattr->ptlViewportOrg.x += nXOffset; 896 pdcattr->ptlViewportOrg.y += nYOffset; 897 } 898 899 HANDLE_EMETAFDC(BOOL, SetViewportOrgEx, FALSE, hdc, pdcattr->ptlViewportOrg.x, pdcattr->ptlViewportOrg.y); 900 901 return TRUE; 902 903 // return NtGdiOffsetViewportOrgEx(hdc, nXOffset, nYOffset, lpPoint); 904 } 905 906 /* 907 * @implemented 908 * 909 */ 910 BOOL 911 WINAPI 912 OffsetWindowOrgEx( 913 _In_ HDC hdc, 914 _In_ int nXOffset, 915 _In_ int nYOffset, 916 _Out_opt_ LPPOINT lpPoint) 917 { 918 PDC_ATTR pdcattr; 919 920 HANDLE_METADC16(BOOL, OffsetWindowOrgEx, FALSE, hdc, nXOffset, nYOffset); 921 922 /* Get the DC attribute */ 923 pdcattr = GdiGetDcAttr(hdc); 924 if (!pdcattr) 925 { 926 /* Do not set LastError here! */ 927 return FALSE; 928 } 929 930 if ( lpPoint ) 931 { 932 *lpPoint = pdcattr->ptlWindowOrg; 933 //lpPoint->x = pdcattr->lWindowOrgx; 934 } 935 936 if ( nXOffset || nYOffset != nXOffset ) 937 { 938 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc) 939 { 940 if (pdcattr->ulDirty_ & DC_MODE_DIRTY) 941 { 942 NtGdiFlush(); 943 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY; 944 } 945 } 946 947 pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID); 948 pdcattr->ptlWindowOrg.x += nXOffset; 949 pdcattr->ptlWindowOrg.y += nYOffset; 950 pdcattr->lWindowOrgx += nXOffset; 951 } 952 953 HANDLE_EMETAFDC(BOOL, SetWindowOrgEx, FALSE, hdc, pdcattr->ptlWindowOrg.x, pdcattr->ptlWindowOrg.y); 954 955 return TRUE; 956 957 // return NtGdiOffsetWindowOrgEx(hdc, nXOffset, nYOffset, lpPoint); 958 } 959 960