--- winlayout1.108.cxx 2007-12-18 20:35:24.679000000 +0100 +++ winlayout.cxx 2008-02-03 16:57:44.293000000 +0100 @@ -42,6 +42,7 @@ #include #include +#include #ifndef _SV_SALGDI_H #include @@ -70,6 +71,8 @@ #ifdef USE_UNISCRIBE #include +#include +#include #endif // USE_UNISCRIBE #include @@ -1144,6 +1147,8 @@ static HRESULT ((WINAPI *pScriptTextOut) static HRESULT ((WINAPI *pScriptGetFontProperties)( HDC, SCRIPT_CACHE*, SCRIPT_FONTPROPERTIES* )); static HRESULT ((WINAPI *pScriptFreeCache)( SCRIPT_CACHE* )); +static bool bManualCellAlign = true; + // ----------------------------------------------------------------------- static bool InitUSP() @@ -1217,6 +1222,36 @@ static bool InitUSP() aUspModule = NULL; } + // get the DLL version info + int nUspVersion = 0; + // TODO: there must be a simpler way to get the friggin version info from OSL? + rtl_uString* pModuleURL = NULL; + osl_getModuleURLFromAddress( (void*)pScriptIsComplex, &pModuleURL ); + rtl_uString* pModuleFileName = NULL; + if( pModuleURL ) + osl_getSystemPathFromFileURL( pModuleURL, &pModuleFileName ); + const sal_Unicode* pModuleFileCStr = NULL; + if( pModuleFileName ) + pModuleFileCStr = rtl_uString_getStr( pModuleFileName ); + if( pModuleFileCStr ) + { + DWORD nHandle; + DWORD nBufSize = ::GetFileVersionInfoSizeW( pModuleFileCStr, &nHandle ); + char* pBuffer = (char*)alloca( nBufSize ); + WIN_BOOL bRC = ::GetFileVersionInfoW( pModuleFileCStr, nHandle, nBufSize, pBuffer ); + VS_FIXEDFILEINFO* pFixedFileInfo = NULL; + UINT nFixedFileSize = 0; + if( bRC ) + ::VerQueryValueW( pBuffer, L"\\", (void**)&pFixedFileInfo, &nFixedFileSize ); + if( pFixedFileInfo && pFixedFileInfo->dwSignature == 0xFEEF04BD ) + nUspVersion = HIWORD(pFixedFileInfo->dwProductVersionMS) * 10000 + + LOWORD(pFixedFileInfo->dwProductVersionMS); + } + + // #i77976# USP>=1.0600 changed the need to manually align glyphs in their cells + if( nUspVersion >= 10600 ) + bManualCellAlign = false; + return bUspEnabled; } @@ -2306,14 +2341,33 @@ void UniscribeLayout::ApplyDXArray( cons || (rVisualItem.mnEndCharPos <= mnMinCharPos) ) continue; - if( rVisualItem.mpScriptItem->a.fRTL ) + bool bHasKashida = false; + if( rVisualItem.mpScriptItem->a.fRTL ) { - // HACK: make sure kashida justification is used when possible - // TODO: make sure this works on all usp versions - for( i = rVisualItem.mnMinGlyphPos; i < rVisualItem.mnEndGlyphPos; ++i ) - if( (1U << mpVisualAttrs[i].uJustification) & 0x7F89 ) - mpVisualAttrs[i].uJustification = SCRIPT_JUSTIFY_ARABIC_KASHIDA; + for( i = rVisualItem.mnMinGlyphPos; i < rVisualItem.mnEndGlyphPos; ++i ) + if ( (1U << mpVisualAttrs[i].uJustification) & 0x7F89 ) // any Arabic justification ? + { + // yes + bHasKashida = true; + break; + } + if ( bHasKashida ) + for( i = rVisualItem.mnMinGlyphPos; i < rVisualItem.mnEndGlyphPos; ++i ) + { + if ( mpVisualAttrs[i].uJustification == SCRIPT_JUSTIFY_NONE ) + // usp decided that justification can't be applied here + // but maybe our Kashida algorithm thinks differently. + // To avoid trouble (gaps within words, last character of + // a word gets a Kashida appended) override this. + + // I chose SCRIPT_JUSTIFY_ARABIC_KASHIDA to replace SCRIPT_JUSTIFY_NONE + // just because this previous hack (which I haven't understand, sorry) used + // the same value to replace. Don't know if this is really the best + // thing to do, but it seems to fix things + mpVisualAttrs[i].uJustification = SCRIPT_JUSTIFY_ARABIC_KASHIDA; + } } + // convert virtual charwidths to glyph justification values HRESULT nRC = (*pScriptApplyLogicalWidth)( @@ -2334,22 +2388,38 @@ void UniscribeLayout::ApplyDXArray( cons break; } - // update nXOffset to the position of the next visual item - int nEndGlyphPos; - if( GetItemSubrange( rVisualItem, i, nEndGlyphPos ) ) - for(; i < nEndGlyphPos; ++i ) + // TODO: for kashida justification + // check the widths which are added to mpJustification + // if added width is smaller than iKashidaWidth returned by + // ScriptGetFontProperties, do something (either enlarge to + // iKashidaWidth, or reduce to original width). + // Need to think of a way to compensate the change in overall + // width. + + // to prepare for the next visual item + // update nXOffset to the next items position + // before the mpJustifications[] array gets modified + int nMinGlyphPos, nEndGlyphPos; + if( GetItemSubrange( rVisualItem, nMinGlyphPos, nEndGlyphPos ) ) + for( i = nMinGlyphPos; i < nEndGlyphPos; ++i ) nXOffset += mpJustifications[ i ]; - if( rVisualItem.mpScriptItem->a.fRTL ) + // right align the justification-adjusted glyphs in their cells for RTL-items + if( bManualCellAlign && rVisualItem.mpScriptItem->a.fRTL && !bHasKashida ) { - // right align adjusted glyph positions for RTL item - // exception: kashida aligned glyphs - // TODO: make sure this works on all usp versions - for( i = rVisualItem.mnMinGlyphPos+1; i < rVisualItem.mnEndGlyphPos; ++i ) - if( mpVisualAttrs[i].uJustification != SCRIPT_JUSTIFY_ARABIC_KASHIDA ) + for( i = nMinGlyphPos; i < nEndGlyphPos; ++i ) { - mpJustifications[i-1] += mpJustifications[ i ] - mpGlyphAdvances[ i ]; - mpJustifications[ i ] = mpGlyphAdvances[ i ]; + // it is no use to check this per glyph + // either we right align the whole item or we don't + // if( mpVisualAttrs[i].uJustification == SCRIPT_JUSTIFY_ARABIC_KASHIDA ) + // continue; + + const int nXOffsetAdjust = mpJustifications[i] - mpGlyphAdvances[i]; + if( i == nMinGlyphPos ) + rVisualItem.mnXOffset += nXOffsetAdjust; + else + mpJustifications[i-1] += nXOffsetAdjust; + mpJustifications[i] -= nXOffsetAdjust; } } }