Kaydet (Commit) 7a8fcfca authored tarafından Norbert Thiebaud's avatar Norbert Thiebaud

fdo#79673 quartz: draw 'bullet' for 'space' directly in one pass

the current implementation of CoreText simply dropped the proper
implementation of DrawTextArray, by ignoring DXArray
this very visibly borked the show-non-displayable character
feature of writer.. the bullet representing the 'spaces'
was quite misplaced.
This solve specifically this problem.
More work is needed to bring proper support of DXArray back to CoreText


Conflicts:
	vcl/inc/sallayout.hxx
	vcl/source/outdev/text.cxx

Change-Id: Idb2cc90d5ffaa8b83f79241cee2d512112d1c3be
üst 6c8de2b1
...@@ -96,6 +96,21 @@ class VirtualDevice; ...@@ -96,6 +96,21 @@ class VirtualDevice;
class Window; class Window;
struct SalTwoRect; struct SalTwoRect;
// Layout options
#define SAL_LAYOUT_BIDI_RTL (1<<0)
#define SAL_LAYOUT_BIDI_STRONG (1<<1)
#define SAL_LAYOUT_RIGHT_ALIGN (1<<2)
#define SAL_LAYOUT_KERNING_PAIRS (1<<4)
#define SAL_LAYOUT_KERNING_ASIAN (1<<5)
#define SAL_LAYOUT_VERTICAL (1<<6)
#define SAL_LAYOUT_COMPLEX_DISABLED (1<<8)
#define SAL_LAYOUT_ENABLE_LIGATURES (1<<9)
#define SAL_LAYOUT_SUBSTITUTE_DIGITS (1<<10)
#define SAL_LAYOUT_KASHIDA_JUSTIFICATON (1<<11)
#define SAL_LAYOUT_DISABLE_GLYPH_PROCESSING (1<<12)
#define SAL_LAYOUT_FOR_FALLBACK (1<<13)
#define SAL_LAYOUT_DRAW_BULLET (1<<14)
namespace com { namespace com {
namespace sun { namespace sun {
namespace star { namespace star {
...@@ -1071,7 +1086,8 @@ public: ...@@ -1071,7 +1086,8 @@ public:
void DrawTextArray( const Point& rStartPt, const OUString& rStr, void DrawTextArray( const Point& rStartPt, const OUString& rStr,
const sal_Int32* pDXAry = NULL, const sal_Int32* pDXAry = NULL,
sal_Int32 nIndex = 0, sal_Int32 nIndex = 0,
sal_Int32 nLen = -1 ); sal_Int32 nLen = -1,
int flags = 0);
long GetTextArray( const OUString& rStr, sal_Int32* pDXAry = NULL, long GetTextArray( const OUString& rStr, sal_Int32* pDXAry = NULL,
sal_Int32 nIndex = 0, sal_Int32 nLen = -1 ) const; sal_Int32 nIndex = 0, sal_Int32 nLen = -1 ) const;
...@@ -1081,7 +1097,7 @@ public: ...@@ -1081,7 +1097,7 @@ public:
bool bCellBreaking = true ) const; bool bCellBreaking = true ) const;
void DrawStretchText( const Point& rStartPt, sal_uLong nWidth, void DrawStretchText( const Point& rStartPt, sal_uLong nWidth,
const OUString& rStr, const OUString& rStr,
sal_Int32 nIndex = 0, sal_Int32 nLen = -1 ); sal_Int32 nIndex = 0, sal_Int32 nLen = -1);
sal_Int32 GetTextBreak( const OUString& rStr, long nTextWidth, sal_Int32 GetTextBreak( const OUString& rStr, long nTextWidth,
sal_Int32 nIndex = 0, sal_Int32 nLen = -1, sal_Int32 nIndex = 0, sal_Int32 nLen = -1,
long nCharExtra = 0 ) const; long nCharExtra = 0 ) const;
...@@ -1230,9 +1246,9 @@ public: ...@@ -1230,9 +1246,9 @@ public:
virtual bool HasMirroredGraphics() const; virtual bool HasMirroredGraphics() const;
SAL_DLLPRIVATE SalLayout* ImplLayout( const OUString&, sal_Int32 nIndex, sal_Int32 nLen, SAL_DLLPRIVATE SalLayout* ImplLayout( const OUString&, sal_Int32 nIndex, sal_Int32 nLen,
const Point& rLogicPos = Point(0,0), long nLogicWidth=0, const Point& rLogicPos = Point(0,0), long nLogicWidth=0,
const sal_Int32* pLogicDXArray=NULL ) const; const sal_Int32* pLogicDXArray=NULL, int flags=0 ) const;
SAL_DLLPRIVATE ImplLayoutArgs ImplPrepareLayoutArgs( OUString&, const sal_Int32 nIndex, const sal_Int32 nLen, SAL_DLLPRIVATE ImplLayoutArgs ImplPrepareLayoutArgs( OUString&, const sal_Int32 nIndex, const sal_Int32 nLen,
long nPixelWidth, const sal_Int32* pPixelDXArray ) const; long nPixelWidth, const sal_Int32* pPixelDXArray, int flags = 0 ) const;
SAL_DLLPRIVATE SalLayout* ImplGlyphFallbackLayout( SalLayout*, ImplLayoutArgs& ) const; SAL_DLLPRIVATE SalLayout* ImplGlyphFallbackLayout( SalLayout*, ImplLayoutArgs& ) const;
// tells whether this output device is RTL in an LTR UI or LTR in a RTL UI // tells whether this output device is RTL in an LTR UI or LTR in a RTL UI
SAL_DLLPRIVATE SalLayout* getFallbackFont(ImplFontEntry &rFallbackFont, SAL_DLLPRIVATE SalLayout* getFallbackFont(ImplFontEntry &rFallbackFont,
......
...@@ -1275,7 +1275,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) ...@@ -1275,7 +1275,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
// If it is a single underlined space, output 2 spaces: // If it is a single underlined space, output 2 spaces:
if( 1 == rInf.GetLen() ) if( 1 == rInf.GetLen() )
{ {
pKernArray[0] = rInf.GetWidth() + nSpaceAdd; pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(), rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), 1 ); pKernArray, rInf.GetIdx(), 1 );
...@@ -1352,8 +1352,11 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) ...@@ -1352,8 +1352,11 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
else else
{ {
const OUString* pStr = &rInf.GetText(); const OUString* pStr = &rInf.GetText();
#if !defined(MACOSX) && !defined(IOS)
OUString aStr; OUString aStr;
OUString aBulletOverlay; OUString aBulletOverlay;
#endif
bool bBullet = rInf.GetBullet(); bool bBullet = rInf.GetBullet();
if( bSymbol ) if( bSymbol )
bBullet = false; bBullet = false;
...@@ -1463,6 +1466,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) ...@@ -1463,6 +1466,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
nScrPos = pScrArray[ 0 ]; nScrPos = pScrArray[ 0 ];
#if !defined(MACOSX) && !defined(IOS)
if( bBullet ) if( bBullet )
{ {
// !!! HACK !!! // !!! HACK !!!
...@@ -1502,7 +1506,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) ...@@ -1502,7 +1506,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
aBulletOverlay = aBulletOverlay.replaceAt(i, 1, OUString(CH_BLANK)); aBulletOverlay = aBulletOverlay.replaceAt(i, 1, OUString(CH_BLANK));
} }
} }
#endif
sal_Int32 nCnt = rInf.GetText().getLength(); sal_Int32 nCnt = rInf.GetText().getLength();
if ( nCnt < rInf.GetIdx() ) if ( nCnt < rInf.GetIdx() )
nCnt = 0; nCnt = 0;
...@@ -1526,11 +1530,16 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) ...@@ -1526,11 +1530,16 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
if ( bSwitchH2V ) if ( bSwitchH2V )
rInf.GetFrm()->SwitchHorizontalToVertical( aPos ); rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
#if defined(MACOSX) || defined(IOS)
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), 1, bBullet ? SAL_LAYOUT_DRAW_BULLET : 0 );
#else
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(), rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), 1 ); pKernArray, rInf.GetIdx(), 1 );
if( bBullet ) if( bBullet )
rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray, rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray,
rInf.GetIdx() ? 1 : 0, 1 ); rInf.GetIdx() ? 1 : 0, 1 );
#endif
} }
else else
{ {
...@@ -1708,13 +1717,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) ...@@ -1708,13 +1717,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
if( nOffs < nLen ) if( nOffs < nLen )
{ {
// If we paint bullets instead of spaces, we use a copy of
// the paragraph string. For the layout engine, the copy
// of the string has to be an environment of the range which
// is painted
sal_Int32 nTmpIdx = bBullet ?
( rInf.GetIdx() ? 1 : 0 ) :
rInf.GetIdx();
if ( bSwitchL2R ) if ( bSwitchL2R )
rInf.GetFrm()->SwitchLTRtoRTL( aPos ); rInf.GetFrm()->SwitchLTRtoRTL( aPos );
...@@ -1722,6 +1724,17 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) ...@@ -1722,6 +1724,17 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
if ( bSwitchH2V ) if ( bSwitchH2V )
rInf.GetFrm()->SwitchHorizontalToVertical( aPos ); rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
#if defined(MACOSX) || defined(IOS)
rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray + nOffs,
rInf.GetIdx() + nOffs , nLen - nOffs, bBullet ? SAL_LAYOUT_DRAW_BULLET : 0 );
#else
// If we paint bullets instead of spaces, we use a copy of
// the paragraph string. For the layout engine, the copy
// of the string has to be an environment of the range which
// is painted
sal_Int32 nTmpIdx = bBullet ?
( rInf.GetIdx() ? 1 : 0 ) :
rInf.GetIdx();
rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray + nOffs, rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray + nOffs,
nTmpIdx + nOffs , nLen - nOffs ); nTmpIdx + nOffs , nLen - nOffs );
if (bBullet) if (bBullet)
...@@ -1747,6 +1760,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) ...@@ -1747,6 +1760,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
pTmpFont->SetStrikeout(aPreviousStrikeout); pTmpFont->SetStrikeout(aPreviousStrikeout);
rInf.GetOut().Pop(); rInf.GetOut().Pop();
} }
#endif
} }
} }
delete[] pScrArray; delete[] pScrArray;
......
...@@ -40,19 +40,6 @@ typedef unsigned short LanguageType; ...@@ -40,19 +40,6 @@ typedef unsigned short LanguageType;
class SalGraphics; class SalGraphics;
class PhysicalFontFace; class PhysicalFontFace;
// Layout options
#define SAL_LAYOUT_BIDI_RTL 0x0001
#define SAL_LAYOUT_BIDI_STRONG 0x0002
#define SAL_LAYOUT_RIGHT_ALIGN 0x0004
#define SAL_LAYOUT_KERNING_PAIRS 0x0010
#define SAL_LAYOUT_KERNING_ASIAN 0x0020
#define SAL_LAYOUT_VERTICAL 0x0040
#define SAL_LAYOUT_COMPLEX_DISABLED 0x0100
#define SAL_LAYOUT_ENABLE_LIGATURES 0x0200
#define SAL_LAYOUT_SUBSTITUTE_DIGITS 0x0400
#define SAL_LAYOUT_KASHIDA_JUSTIFICATON 0x0800
#define SAL_LAYOUT_DISABLE_GLYPH_PROCESSING 0x1000
#define SAL_LAYOUT_FOR_FALLBACK 0x2000
// used for managing runs e.g. for BiDi, glyph and script fallback // used for managing runs e.g. for BiDi, glyph and script fallback
class VCL_PLUGIN_PUBLIC ImplLayoutRuns class VCL_PLUGIN_PUBLIC ImplLayoutRuns
...@@ -99,7 +86,8 @@ public: ...@@ -99,7 +86,8 @@ public:
public: public:
ImplLayoutArgs( const sal_Unicode* pStr, int nLength, ImplLayoutArgs( const sal_Unicode* pStr, int nLength,
int nMinCharPos, int nEndCharPos, int nFlags, const LanguageTag& rLanguageTag ); int nMinCharPos, int nEndCharPos, int nFlags,
const LanguageTag& rLanguageTag );
void SetLayoutWidth( long nWidth ) { mnLayoutWidth = nWidth; } void SetLayoutWidth( long nWidth ) { mnLayoutWidth = nWidth; }
void SetDXArray( const sal_Int32* pDXArray ) { mpDXArray = pDXArray; } void SetDXArray( const sal_Int32* pDXArray ) { mpDXArray = pDXArray; }
......
...@@ -380,6 +380,60 @@ void CTLayout::drawCTLine(AquaSalGraphics& rAquaGraphics, CTLineRef ctline, cons ...@@ -380,6 +380,60 @@ void CTLayout::drawCTLine(AquaSalGraphics& rAquaGraphics, CTLineRef ctline, cons
// draw the text // draw the text
CTLineDraw( ctline, rAquaGraphics.mrContext ); CTLineDraw( ctline, rAquaGraphics.mrContext );
if(mnLayoutFlags & SAL_LAYOUT_DRAW_BULLET)
{
CFArrayRef runArray = CTLineGetGlyphRuns(ctline);
CFIndex runCount = CFArrayGetCount(runArray);
CFIndex runIndex = 0;
CTLineRef ctlinebullet = 0;
OUString sBullet((sal_Unicode)0xb7); // centered bullet
for (; runIndex < runCount; runIndex++)
{
CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex);
CFIndex runGlyphCount = CTRunGetGlyphCount(run);
CGPoint position;
CFIndex runGlyphIndex = 0;
CFIndex stringIndice = 0;
for (; runGlyphIndex < runGlyphCount; runGlyphIndex++)
{
CFRange glyphRange = CFRangeMake(runGlyphIndex, 1);
CTRunGetStringIndices( run, glyphRange, &stringIndice );
UniChar curChar = CFStringGetCharacterAtIndex (CFAttributedStringGetString(mpAttrString), stringIndice);
if(curChar == ' ')
{
CTRunGetPositions(run, glyphRange, &position);
// print a dot
if(!ctlinebullet)
{
CFStringRef aCFText = CFStringCreateWithCharactersNoCopy( NULL,
sBullet.getStr(),
1,
kCFAllocatorNull );
// CFAttributedStringCreate copies the attribues parameter
CFAttributedStringRef bulletAttrString = CFAttributedStringCreate( NULL, aCFText, mpTextStyle->GetStyleDict() );
ctlinebullet = CTLineCreateWithAttributedString( bulletAttrString );
CFRelease( aCFText);
CFRelease( bulletAttrString);
RGBAColor bulletColor(MAKE_SALCOLOR(0x26, 0x8b, 0xd2 )); // NON_PRINTING_CHARACTER_COLOR
CGContextSetFillColor( rAquaGraphics.mrContext, bulletColor.AsArray() );
}
CGContextSetTextPosition( rAquaGraphics.mrContext, aTextPos.x + position.x, position.y + aTextPos.y );
CTLineDraw(ctlinebullet, rAquaGraphics.mrContext);
}
}
}
if(ctlinebullet)
{
CFRelease(ctlinebullet);
}
}
// restore the original graphic context transformations // restore the original graphic context transformations
SAL_INFO( "vcl.ct", "CGContextRestoreGState(" << rAquaGraphics.mrContext << ")" ); SAL_INFO( "vcl.ct", "CGContextRestoreGState(" << rAquaGraphics.mrContext << ")" );
CGContextRestoreGState( rAquaGraphics.mrContext ); CGContextRestoreGState( rAquaGraphics.mrContext );
......
...@@ -281,8 +281,8 @@ bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout ) ...@@ -281,8 +281,8 @@ bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout )
} }
bool OutputDevice::ImplDrawTextDirect( SalLayout& rSalLayout, bool OutputDevice::ImplDrawTextDirect( SalLayout& rSalLayout,
bool bTextLines, bool bTextLines,
sal_uInt32 flags ) sal_uInt32 flags )
{ {
if( mpFontEntry->mnOwnOrientation ) if( mpFontEntry->mnOwnOrientation )
if( ImplDrawRotateText( rSalLayout ) ) if( ImplDrawRotateText( rSalLayout ) )
...@@ -950,7 +950,7 @@ float OutputDevice::approximate_char_width() const ...@@ -950,7 +950,7 @@ float OutputDevice::approximate_char_width() const
void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr,
const sal_Int32* pDXAry, const sal_Int32* pDXAry,
sal_Int32 nIndex, sal_Int32 nLen ) sal_Int32 nIndex, sal_Int32 nLen, int flags )
{ {
if(nLen == 0x0FFFF) if(nLen == 0x0FFFF)
{ {
...@@ -973,7 +973,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, ...@@ -973,7 +973,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr,
if( mbOutputClipped ) if( mbOutputClipped )
return; return;
SalLayout* pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, pDXAry); SalLayout* pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, pDXAry, flags);
if( pSalLayout ) if( pSalLayout )
{ {
ImplDrawText( *pSalLayout ); ImplDrawText( *pSalLayout );
...@@ -981,7 +981,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, ...@@ -981,7 +981,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr,
} }
if( mpAlphaVDev ) if( mpAlphaVDev )
mpAlphaVDev->DrawTextArray( rStartPt, rStr, pDXAry, nIndex, nLen ); mpAlphaVDev->DrawTextArray( rStartPt, rStr, pDXAry, nIndex, nLen, flags );
} }
long OutputDevice::GetTextArray( const OUString& rStr, sal_Int32* pDXAry, long OutputDevice::GetTextArray( const OUString& rStr, sal_Int32* pDXAry,
...@@ -1101,7 +1101,7 @@ bool OutputDevice::GetCaretPositions( const OUString& rStr, sal_Int32* pCaretXAr ...@@ -1101,7 +1101,7 @@ bool OutputDevice::GetCaretPositions( const OUString& rStr, sal_Int32* pCaretXAr
void OutputDevice::DrawStretchText( const Point& rStartPt, sal_uLong nWidth, void OutputDevice::DrawStretchText( const Point& rStartPt, sal_uLong nWidth,
const OUString& rStr, const OUString& rStr,
sal_Int32 nIndex, sal_Int32 nLen ) sal_Int32 nIndex, sal_Int32 nLen)
{ {
if(nIndex < 0 || nIndex == 0x0FFFF || nLen == 0x0FFFF) if(nIndex < 0 || nIndex == 0x0FFFF || nLen == 0x0FFFF)
{ {
...@@ -1131,8 +1131,9 @@ void OutputDevice::DrawStretchText( const Point& rStartPt, sal_uLong nWidth, ...@@ -1131,8 +1131,9 @@ void OutputDevice::DrawStretchText( const Point& rStartPt, sal_uLong nWidth,
} }
ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr,
const sal_Int32 nMinIndex, const sal_Int32 nLen, const sal_Int32 nMinIndex, const sal_Int32 nLen,
long nPixelWidth, const sal_Int32* pDXArray ) const long nPixelWidth, const sal_Int32* pDXArray,
int nLayoutFlags ) const
{ {
assert(nMinIndex >= 0); assert(nMinIndex >= 0);
assert(nLen >= 0); assert(nLen >= 0);
...@@ -1146,7 +1147,6 @@ ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, ...@@ -1146,7 +1147,6 @@ ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr,
if( nEndIndex < nMinIndex ) if( nEndIndex < nMinIndex )
nEndIndex = nMinIndex; nEndIndex = nMinIndex;
int nLayoutFlags = 0;
if( mnTextLayoutMode & TEXT_LAYOUT_BIDI_RTL ) if( mnTextLayoutMode & TEXT_LAYOUT_BIDI_RTL )
nLayoutFlags |= SAL_LAYOUT_BIDI_RTL; nLayoutFlags |= SAL_LAYOUT_BIDI_RTL;
if( mnTextLayoutMode & TEXT_LAYOUT_BIDI_STRONG ) if( mnTextLayoutMode & TEXT_LAYOUT_BIDI_STRONG )
...@@ -1244,9 +1244,9 @@ ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, ...@@ -1244,9 +1244,9 @@ ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr,
} }
SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr, SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr,
sal_Int32 nMinIndex, sal_Int32 nLen, sal_Int32 nMinIndex, sal_Int32 nLen,
const Point& rLogicalPos, long nLogicalWidth, const Point& rLogicalPos, long nLogicalWidth,
const sal_Int32* pDXArray) const const sal_Int32* pDXArray, int flags) const
{ {
// we need a graphics // we need a graphics
if( !mpGraphics ) if( !mpGraphics )
...@@ -1292,7 +1292,7 @@ SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr, ...@@ -1292,7 +1292,7 @@ SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr,
pDXArray = pTempDXAry; pDXArray = pTempDXAry;
} }
ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStr, nMinIndex, nLen, nPixelWidth, pDXArray ); ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStr, nMinIndex, nLen, nPixelWidth, pDXArray, flags);
// get matching layout object for base font // get matching layout object for base font
SalLayout* pSalLayout = mpGraphics->GetTextLayout( aLayoutArgs, 0 ); SalLayout* pSalLayout = mpGraphics->GetTextLayout( aLayoutArgs, 0 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment