--- winlayout.1.108.206.2.cxx 2008-03-05 13:57:13.567000000 +0000 +++ winlayout.cxx 2008-04-06 21:58:25.380000000 +0000 @@ -1120,6 +1120,9 @@ private: GOFFSET* mpGlyphOffsets; // glyph offsets to the "naive" layout SCRIPT_VISATTR* mpVisualAttrs; // glyph visual attributes mutable int* mpGlyphs2Chars; // map from absolute_glyph_pos to absolute_char_pos + + // font specific info + int mnMinKashidaWidth; // minimal Kashida width allowed by font }; // ----------------------------------------------------------------------- @@ -1685,11 +1688,23 @@ bool UniscribeLayout::LayoutText( ImplLa } } + //ScriptGetFontProperties + + SCRIPT_FONTPROPERTIES aFontProperties; + aFontProperties.cBytes = sizeof (aFontProperties); // don't forget to initialize + mnMinKashidaWidth = 0; + HRESULT nRC = (*pScriptGetFontProperties)( mhDC, &rScriptCache, &aFontProperties ); + if( !nRC ) + { + mnMinKashidaWidth = aFontProperties.iKashidaWidth; + } + + // scale layout metrics if needed if( mfFontScale != 1.0 ) { mnBaseAdv = (int)((double)mnBaseAdv*mfFontScale); - + mnMinKashidaWidth = (int)((double)mnMinKashidaWidth*mfFontScale); for( i = 0; i < mnItemCount; ++i ) mpVisualItems[i].mnXOffset = (int)((double)mpVisualItems[i].mnXOffset*mfFontScale); @@ -2354,16 +2369,18 @@ void UniscribeLayout::ApplyDXArray( cons if( rVisualItem.mpScriptItem->a.fRTL ) { for( i = rVisualItem.mnMinGlyphPos; i < rVisualItem.mnEndGlyphPos; ++i ) - if ( (1U << mpVisualAttrs[i].uJustification) & 0x7F89 ) // any Arabic justification ? - { - // yes + if ( (1U << mpVisualAttrs[i].uJustification) & 0xFF89 ) // any Arabic justification ? + { // the last SCRIPT_JUSTIFY_xxx + // yes // == 15 (usp 1.6) bHasKashida = true; break; } if ( bHasKashida ) for( i = rVisualItem.mnMinGlyphPos; i < rVisualItem.mnEndGlyphPos; ++i ) { - if ( mpVisualAttrs[i].uJustification == SCRIPT_JUSTIFY_NONE ) + // check if we still need this hack after correction of kashida placing? + // (i87688): apparently yes, we still need it! + 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 @@ -2397,6 +2414,15 @@ void UniscribeLayout::ApplyDXArray( cons break; } + // 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 ]; + // TODO: for kashida justification // check the widths which are added to mpJustification // if added width is smaller than iKashidaWidth returned by @@ -2405,13 +2431,60 @@ void UniscribeLayout::ApplyDXArray( cons // 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 ( bHasKashida && mnMinKashidaWidth ) + { + int nSpaceAdded; + for ( i = nMinGlyphPos; i < nEndGlyphPos; ++i ) + { + nSpaceAdded = mpJustifications[ i ] - mpGlyphAdvances[ i ]; + if ( nSpaceAdded && ((1U << mpVisualAttrs[i].uJustification) & 0xFF89 )) + { + if ( i > nMinGlyphPos && ! mpGlyphAdvances [ i - 1 ] && nSpaceAdded >= mnMinKashidaWidth) + { + // vowel, we do it like ScriptJustify does + // this works great !!! + mpJustifications [ i ] = mpGlyphAdvances [ i ]; + mpJustifications [ i - 1 ] += nSpaceAdded; + } + + if ( nSpaceAdded < mnMinKashidaWidth ) + { + mpJustifications[ i ] = mpGlyphAdvances[ i ]; // overriding; + /*for ( int j = i; j >= nMinGlyphPos; --j ) + { + if ( mpVisualAttrs[ j ].uJustification == SCRIPT_JUSTIFY_ARABIC_BLANK ) + { + mpJustifications [ j ] += nSpaceAdded; // padding a blank instead + nSpaceAdded = 0; + break; + } + }*/ + + // no blank found + // try the other side + for ( int j = i; j < nEndGlyphPos; ++j ) + { + if ( mpVisualAttrs[ j ].uJustification == SCRIPT_JUSTIFY_ARABIC_BLANK ) + { + mpJustifications [ j ] += nSpaceAdded; // padding a blank instead + nSpaceAdded = 0; + break; + } + } + + if ( nSpaceAdded ) + { + // no blank found + // right align + // rVisualItem.mnXOffset += nSpaceAdded; + } + } + } + } + } + } + + // right align the justification-adjusted glyphs in their cells for RTL-items if( bManualCellAlign && rVisualItem.mpScriptItem->a.fRTL && !bHasKashida ) @@ -2466,6 +2539,7 @@ void UniscribeLayout::Justify( long nNew nItemWidth = (int)((fStretch - 1.0) * nItemWidth + 0.5); SCRIPT_FONTPROPERTIES aFontProperties; + aFontProperties.cBytes = sizeof (aFontProperties); // don't forget to initialize int nMinKashida = 1; HRESULT nRC = (*pScriptGetFontProperties)( mhDC, &rScriptCache, &aFontProperties ); if( !nRC )