Changeset 21997 for trunk/src


Ignore:
Timestamp:
Apr 10, 2012, 9:55:43 PM (13 years ago)
Author:
dmik
Message:

gdi32: Fix lost text in TextOut when used with non-identity trasformation matrix.

This was a regression of r21628 wchich I completely reverted. See #81 for details.

Location:
trunk/src/gdi32
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gdi32/ft2supp.cpp

    r21916 r21997  
    199199DWORD CFT2Module::Ft2GetGlyphIndices(HPS hps, LPCWSTR str, int c, LPWORD pgi, DWORD fl)
    200200{
    201     DWORD  ret;
    202     USHORT sel;
    203 
    204     // All FreeType calls should be wrapped for saving FS
     201    DWORD  ret; 
     202    USHORT sel;
     203
     204    // All FreeType calls should be wrapped for saving FS 
    205205    if(pfnGetGlyphIndices) {
    206206        sel  = RestoreOS2FS();
    207207        ret  = pfnGetGlyphIndices(hps, (WCHAR*)str, c, (ULONG*)pgi, fl);
    208208        SetFS(sel);
    209         return ret;
     209        return ret; 
    210210    }
    211211    //no fallback
     
    217217DWORD CFT2Module::Ft2GetGlyphOutline(HPS hps, UINT glyph, UINT format, LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf, const MAT2* lpmat)
    218218{
    219     DWORD  ret;
    220     USHORT sel;
    221 
    222     // All FreeType calls should be wrapped for saving FS
     219    DWORD  ret; 
     220    USHORT sel;
     221
     222    // All FreeType calls should be wrapped for saving FS 
    223223    if (pfnFt2GetGlyphOutline)
    224224    {
     
    226226        ret  = pfnFt2GetGlyphOutline (hps, glyph, format, lpgm, buflen, buf, lpmat);
    227227        SetFS(sel);
    228         return ret;
    229     }
    230 
     228        return ret; 
     229    }
     230   
    231231    //no fallback
    232232    SetLastError(ERROR_INVALID_FUNCTION_W);
     
    313313//******************************************************************************
    314314//******************************************************************************
    315 struct CTISTATE
    316 {
    317     pDCData pHps;
    318     BOOL restoreInversion;
    319     BOOL restoreMatrix;
    320     LONG oldYInversion;
    321     MATRIXLF mlf;
    322 };
    323 
    324 static void CompensateTextInversion(pDCData pHps, PPOINTLOS2 ptl, PRECTLOS2 rct,
    325                                     CTISTATE *state)
    326 {
    327     state->pHps = pHps;
    328     state->restoreInversion = FALSE;
    329     state->restoreMatrix = FALSE;
    330 
    331     // The target HPS is most likely set up for Y inversion, to bring the origin
    332     // from the bottom-left corner (PM) to the top-left (Win). However, PM text
    333     // drawing routines make an exception for themselves and produce correct
    334     // top-left oriented glyphs despite the bottom-left oriented coordinate
    335     // space. Having the mentioned Y inversion makes them flip and display
    336     // glyphs top to bottom. We need to cancel this flip to get the correct
    337     // text orientation.
    338 
    339     GpiQueryDefaultViewMatrix(pHps->hps, 9, &state->mlf);
    340 
    341     if (state->mlf.fxM11 == MAKEFIXED(1, 0) && state->mlf.fxM12 == 0 &&
    342         state->mlf.lM13 == 0 &&
    343         state->mlf.fxM21 == 0 && state->mlf.fxM22 == MAKEFIXED(1, 0) &&
    344         state->mlf.lM23 == 0 &&
    345         state->mlf.lM31 == 0 && state->mlf.lM32 == 0 && state->mlf.lM33 == 1)
     315BOOL CFT2Module::Ft2CharStringPosAtA(HPS hps,PPOINTLOS2 ptl,PRECTLOS2 rct,ULONG flOptions,LONG lCount,LPCSTR pchString,CONST INT *alAdx, DWORD fuWin32Options)
     316{
     317    DWORD  ret;
     318    USHORT sel;
     319
     320    // All FreeType calls should be wrapped for saving FS
     321    if(pfnFt2CharStringPosAtA) {
     322        sel  = RestoreOS2FS();
     323        ret  = pfnFt2CharStringPosAtA(hps, ptl,rct,flOptions,lCount,pchString,alAdx, fuWin32Options);
     324        SetFS(sel);
     325        if(ret || (ret == FALSE && ERRORIDERROR(WinGetLastError(0)) != PMERR_FUNCTION_NOT_SUPPORTED))
     326            return ret;
     327    }
     328    //else fall back to GPI
     329    //NOTE: We don't support fuWin32Options in the fallback case
     330    pDCData pHps = (pDCData)OSLibGpiQueryDCData(hps);
     331    return OSLibGpiCharStringPosAt(pHps,ptl,rct,flOptions,lCount,pchString,alAdx);
     332}
     333//******************************************************************************
     334//******************************************************************************
     335BOOL CFT2Module::Ft2CharStringPosAtW(HPS hps, PPOINTLOS2 ptl,PRECTLOS2 rct,ULONG flOptions,LONG lCount,LPCWSTR pchString,CONST INT *alAdx, DWORD fuWin32Options)
     336{
     337    DWORD  ret;
     338    USHORT sel;
     339
     340    // All FreeType calls should be wrapped for saving FS
     341    if(pfnFt2CharStringPosAtW) {
     342        sel  = RestoreOS2FS();
     343        ret  = pfnFt2CharStringPosAtW(hps, ptl,rct,flOptions,lCount,pchString,alAdx, fuWin32Options);
     344        SetFS(sel);
     345        if(ret || (ret == FALSE && ERRORIDERROR(WinGetLastError(0)) != PMERR_FUNCTION_NOT_SUPPORTED))
     346            return ret;
     347    }
     348    //else fall back to GPI
     349    //NOTE: We don't support fuWin32Options in the fallback case
     350    int   len;
     351    LPSTR astring;
     352    LPINT lpDx = NULL;
     353
     354    pDCData pHps = (pDCData)OSLibGpiQueryDCData(hps);
     355
     356    len = WideCharToMultiByte( CP_ACP, 0, pchString, lCount, 0, 0, NULL, NULL );
     357    astring = (char *)malloc( len + 1 );
     358    lstrcpynWtoA(astring, pchString, len + 1 );
     359
     360    if( IsDBCSEnv() && alAdx )
    346361    {
    347         // the most common case: the identity matrix, the inversion is done...
    348 #ifdef INVERT
    349         // ...through the special GPI call, cancel it and correct ptl/rct
    350         state->oldYInversion = GpiQueryYInversion(pHps->hps);
    351         if (state->oldYInversion != 0)
     362        int i, j;
     363
     364        lpDx = ( LPINT )malloc( len * sizeof( INT ));
     365        for( i = j = 0; i < len; i++, j++ )
    352366        {
    353             ptl->y = state->oldYInversion - ptl->y;
    354             if (rct)
    355             {
    356                 LONG temp = state->oldYInversion - rct->yBottom;
    357                 rct->yBottom = state->oldYInversion - rct->yTop;
    358                 rct->yTop = temp;
    359             }
    360 
    361             GpiEnableYInversion(pHps->hps, 0);
    362 
    363             state->restoreInversion = TRUE;
     367            lpDx[ i ] = alAdx[ j ];
     368            if( IsDBCSLeadByte( astring[ i ]))
     369                lpDx[ ++i ] = 0;
    364370        }
    365 #else
    366         // through the raw yInvert value
    367         if (pHps->yInvert > 0)
    368         {
    369             LONG temp = pHps->yInvert - rct->yBottom;
    370             rct->yBottom = pHps->yInvert - rct->yTop;
    371             rct->yTop = temp;
    372         }
    373 #endif
    374     }
    375     else
    376     {
    377         // the complex case: append a matrix transformation that will flip the
    378         // text along the ptl's Y coordinate
    379         MATRIXLF mlf;
    380         mlf.fxM11 = MAKEFIXED(1, 0);
    381         mlf.fxM12 = 0;
    382         mlf.lM13  = 0;
    383         mlf.fxM21 = 0;
    384         mlf.fxM22 = MAKEFIXED(-1, 0);
    385         mlf.lM23  = 0;
    386         mlf.lM31  = 0;
    387         mlf.lM32  = ptl->y * 2;
    388         GpiSetDefaultViewMatrix(pHps->hps, 8, &mlf, TRANSFORM_ADD);
    389 
    390         state->restoreMatrix = TRUE;
    391     }
    392 }
    393 
    394 static void UncompensateTextInversion(CTISTATE *state)
    395 {
    396     if (state->restoreInversion)
    397         GpiEnableYInversion(state->pHps->hps, state->oldYInversion);
    398     if (state->restoreMatrix)
    399         GpiSetDefaultViewMatrix(state->pHps->hps, 9, &state->mlf,
    400                                 TRANSFORM_REPLACE);
    401 }
    402 //******************************************************************************
    403 //******************************************************************************
    404 BOOL CFT2Module::Ft2CharStringPosAtA(HPS hps,PPOINTLOS2 ptl,PRECTLOS2 rct,ULONG flOptions,LONG lCount,LPCSTR pchString,CONST INT *alAdx, DWORD fuWin32Options)
    405 {
    406     DWORD  ret;
    407     USHORT sel;
    408     pDCData pHps;
    409 
    410     pHps = (pDCData)OSLibGpiQueryDCData(hps);
    411 
    412     CTISTATE ctiState;
    413     CompensateTextInversion(pHps, ptl, rct, &ctiState);
    414 
    415     BOOL fallback = TRUE;
    416 
    417     if(pfnFt2CharStringPosAtA)
    418     {
    419         // All FreeType calls should be wrapped for saving FS
    420         sel  = RestoreOS2FS();
    421         ret  = pfnFt2CharStringPosAtA(hps, ptl,rct,flOptions,lCount,pchString,alAdx, fuWin32Options);
    422         SetFS(sel);
    423         if(ret || (ret == FALSE && ERRORIDERROR(WinGetLastError(0)) != PMERR_FUNCTION_NOT_SUPPORTED))
    424             fallback = FALSE;
    425     }
    426 
    427     if (fallback)
    428     {
    429         //else fall back to GPI
    430         //NOTE: We don't support fuWin32Options in the fallback case
    431         ret = OSLibGpiCharStringPosAt(pHps,ptl,rct,flOptions,lCount,pchString,alAdx);
    432     }
    433 
    434     UncompensateTextInversion(&ctiState);
    435 
    436     return ret;
    437 }
    438 //******************************************************************************
    439 //******************************************************************************
    440 BOOL CFT2Module::Ft2CharStringPosAtW(HPS hps, PPOINTLOS2 ptl,PRECTLOS2 rct,ULONG flOptions,LONG lCount,LPCWSTR pchString,CONST INT *alAdx, DWORD fuWin32Options)
    441 {
    442     DWORD  ret;
    443     USHORT sel;
    444     pDCData pHps;
    445 
    446     pHps = (pDCData)OSLibGpiQueryDCData(hps);
    447 
    448     CTISTATE ctiState;
    449     CompensateTextInversion(pHps, ptl, rct, &ctiState);
    450 
    451     BOOL fallback = TRUE;
    452 
    453     if (pfnFt2CharStringPosAtW)
    454     {
    455         // All FreeType calls should be wrapped for saving FS
    456         sel  = RestoreOS2FS();
    457         ret  = pfnFt2CharStringPosAtW(hps, ptl,rct,flOptions,lCount,pchString,alAdx, fuWin32Options);
    458         SetFS(sel);
    459         if(ret || (ret == FALSE && ERRORIDERROR(WinGetLastError(0)) != PMERR_FUNCTION_NOT_SUPPORTED))
    460             fallback = FALSE;
    461     }
    462 
    463     if (fallback)
    464     {
    465         // fall back to GPI
    466         // NOTE: We don't support fuWin32Options in the fallback case
    467         int   len;
    468         LPSTR astring;
    469 
    470         LPINT lpDx = NULL;
    471 
    472         len = WideCharToMultiByte( CP_ACP, 0, pchString, lCount, 0, 0, NULL, NULL );
    473         astring = (char *)malloc( len + 1 );
    474         lstrcpynWtoA(astring, pchString, len + 1 );
    475 
    476         if( IsDBCSEnv() && alAdx )
    477         {
    478             int i, j;
    479 
    480             lpDx = ( LPINT )malloc( len * sizeof( INT ));
    481             for( i = j = 0; i < len; i++, j++ )
    482             {
    483                 lpDx[ i ] = alAdx[ j ];
    484                 if( IsDBCSLeadByte( astring[ i ]))
    485                     lpDx[ ++i ] = 0;
    486             }
    487 
    488             alAdx = ( CONST INT * )lpDx;
    489         }
    490 
    491         ret = OSLibGpiCharStringPosAt(pHps,ptl,rct,flOptions,len,astring,alAdx);
    492 
    493         if( lpDx )
    494             free( lpDx );
    495 
    496         free(astring);
    497     }
    498 
    499     UncompensateTextInversion(&ctiState);
     371
     372        alAdx = ( CONST INT * )lpDx;
     373    }
     374
     375    ret = OSLibGpiCharStringPosAt(pHps,ptl,rct,flOptions,len,astring,alAdx);
     376
     377    if( lpDx )
     378        free( lpDx );
     379
     380    free(astring);
    500381
    501382    return ret;
     
    506387                                 LPVOID lpvBuffer, DWORD cbData)
    507388{
    508     DWORD  ret;
    509     USHORT sel;
    510 
    511     // All FreeType calls should be wrapped for saving FS
     389    DWORD  ret; 
     390    USHORT sel;
     391
     392    // All FreeType calls should be wrapped for saving FS 
    512393    if(pfnFt2GetFontData) {
    513394        sel  = RestoreOS2FS();
     
    515396        SetFS(sel);
    516397        if(ret || (ret == GDI_ERROR && ERRORIDERROR(WinGetLastError(0)) != PMERR_FUNCTION_NOT_SUPPORTED))
    517             return ret;
     398            return ret; 
    518399    }
    519400    //no fallback
     
    665546            lpResults->lpOrder[i] = i;
    666547
    667     // All FreeType calls should be wrapped for saving FS
     548    // All FreeType calls should be wrapped for saving FS 
    668549    if(pfnFt2GetCharacterPlacementW) {
    669550        sel  = RestoreOS2FS();
     
    685566
    686567               if(OSLibDevQueryCaps(pHps, OSLIB_CAPS_HORIZONTAL_RESOLUTION, 2, &alArray[0]) &&
    687                   alArray[0] != alArray[1])
     568                  alArray[0] != alArray[1]) 
    688569               {
    689570                   dprintf(("Different hor/vert resolutions (%d,%d)", alArray[0], alArray[1]));
     
    700581               }
    701582           }
    702            return ret;
     583           return ret; 
    703584        }
    704585    }
  • trunk/src/gdi32/text.cpp

    r21628 r21997  
    9595//******************************************************************************
    9696// todo: metafile support
     97//#undef INVERT
     98//#define INVERT_SETYINVERSION
    9799//******************************************************************************
    98100BOOL InternalTextOutAW(HDC hdc,int X,int Y,UINT fuOptions,
     
    133135  }
    134136
     137#if defined(INVERT) && !defined(INVERT_SETYINVERSION)
     138  if(pHps->yInvert > 0) {
     139     Y = pHps->yInvert - Y;
     140  }
     141#endif
     142
     143#ifdef INVERT_SETYINVERSION
     144  int oldyinv = GpiQueryYInversion(pHps->hps);
     145  Y = oldyinv - Y;
     146#endif
     147
    135148  // When using font association, the height of DBCS and SBCS chars may be different.
    136149  // In this case, background color make stair below chars
     
    168181        return TRUE;
    169182      }
     183#ifndef INVERT
     184#ifdef INVERT_SETYINVERSION
     185      if (oldyinv) {
     186          int temp       = oldyinv - pmRect.yTop;
     187          pmRect.yTop    = oldyinv - pmRect.yBottom;
     188          pmRect.yBottom = temp;
     189      }
     190#else
     191      if (pHps->yInvert > 0) {
     192          int temp       = pHps->yInvert - pmRect.yTop;
     193          pmRect.yTop    = pHps->yInvert - pmRect.yBottom;
     194          pmRect.yBottom = temp;
     195      }
     196#endif
     197#endif
    170198
    171199      if (fuOptions & ETO_CLIPPED) flOptions |= CHSOS_CLIP;
     
    216244    }
    217245  }
     246
     247#ifdef INVERT_SETYINVERSION
     248  GpiEnableYInversion(pHps->hps, 0);
     249#endif
    218250
    219251  if (lpDx)
     
    309341  if(hits == GPIOS_ERROR) {
    310342      dprintf(("InternalTextOutA: OSLibGpiCharStringPosAt returned GPIOS_ERROR"));
     343#ifdef INVERT_SETYINVERSION
     344      GpiEnableYInversion(pHps->hps, oldyinv);
     345#endif
    311346      return FALSE;
    312347  }
     
    321356      OSLibGpiSetCurrentPosition(pHps,&ptl);
    322357  }
     358
     359#ifdef INVERT_SETYINVERSION
     360  GpiEnableYInversion(pHps->hps, oldyinv);
     361#endif
    323362
    324363  DIBSECTION_MARK_INVALID(hdc);
Note: See TracChangeset for help on using the changeset viewer.