summaryrefslogtreecommitdiff
path: root/vcl/aqua
diff options
context:
space:
mode:
authorRelease Engineers <releng@openoffice.org>2008-12-01 15:06:44 +0000
committerRelease Engineers <releng@openoffice.org>2008-12-01 15:06:44 +0000
commitc5f44514bf09ac2030f3beb8b0e4a2b9e22e2e37 (patch)
tree693eb5b452567b8c874fe7911ec8700f2cfbb4db /vcl/aqua
parent0ba2cfaf382582f3ffdf3a13a9ffbd7cda8b68af (diff)
CWS-TOOLING: integrate CWS ooo301gsl1_DEV300
Diffstat (limited to 'vcl/aqua')
-rw-r--r--vcl/aqua/inc/salgdi.h9
-rwxr-xr-xvcl/aqua/source/gdi/salatslayout.cxx204
-rwxr-xr-xvcl/aqua/source/window/salframeview.mm39
3 files changed, 162 insertions, 90 deletions
diff --git a/vcl/aqua/inc/salgdi.h b/vcl/aqua/inc/salgdi.h
index ab603141cc60..4ea1ab4bd2b2 100644
--- a/vcl/aqua/inc/salgdi.h
+++ b/vcl/aqua/inc/salgdi.h
@@ -168,9 +168,9 @@ public:
void ImplDrawPixel( long nX, long nY, const RGBAColor& ); // helper to draw single pixels
bool CheckContext();
- void UpdateWindow( NSRect& rRect ); // delivered in NSView coordinates
+ void UpdateWindow( NSRect& ); // delivered in NSView coordinates
void RefreshRect( const CGRect& );
- void RefreshRect( const NSRect& rRect );
+ void RefreshRect( const NSRect& );
void RefreshRect(float lX, float lY, float lWidth, float lHeight);
void SetState();
@@ -396,6 +396,11 @@ inline void AquaSalGraphics::RefreshRect( const NSRect& rRect )
RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height );
}
+inline void AquaSalGraphics::RefreshRect( const NSRect& rRect )
+{
+ RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height );
+}
+
inline RGBAColor::RGBAColor( SalColor nSalColor )
: mfRed( SALCOLOR_RED(nSalColor) * (1.0/255))
, mfGreen( SALCOLOR_GREEN(nSalColor) * (1.0/255))
diff --git a/vcl/aqua/source/gdi/salatslayout.cxx b/vcl/aqua/source/gdi/salatslayout.cxx
index 42ea2d54f455..a4827870efa9 100755
--- a/vcl/aqua/source/gdi/salatslayout.cxx
+++ b/vcl/aqua/source/gdi/salatslayout.cxx
@@ -74,7 +74,7 @@ private:
float mfFontScale;
private:
- bool InitGIA() const;
+ bool InitGIA( ImplLayoutArgs* pArgs = NULL ) const;
bool GetIdealX() const;
bool GetDeltaY() const;
@@ -96,6 +96,10 @@ private:
mutable Fixed* mpGlyphOrigAdvs; // contains glyph widths for the unjustified layout
mutable Fixed* mpDeltaY; // vertical offset from the baseline
+ struct SubPortion { int mnMinCharPos, mnEndCharPos; Fixed mnXOffset; };
+ typedef std::vector<SubPortion> SubPortionVector;
+ mutable SubPortionVector maSubPortions; // Writer&ATSUI layouts can differ quite a bit...
+
// storing details about fonts used in glyph-fallback for this layout
mutable class FallbackInfo* mpFallbackInfo;
@@ -313,6 +317,10 @@ void ATSLayout::AdjustLayout( ImplLayoutArgs& rArgs )
OSStatus eStatus = ATSUSetLayoutControls( maATSULayout, 3, nTags, nBytes, nVals );
if( eStatus != noErr )
return;
+
+ // check result of the justied layout
+ if( rArgs.mpDXArray )
+ InitGIA( &rArgs );
}
// -----------------------------------------------------------------------
@@ -367,12 +375,23 @@ void ATSLayout::DrawText( SalGraphics& rGraphics ) const
DBG_ASSERT( (theErr==noErr), "ATSLayout::DrawText ATSUSetLayoutControls failed!\n" );
// Draw the text
- DBG_ASSERT( mnBaseAdv==0, "ATSLayout::DrawText() not yet implemented for glyph fallback layouts" );
const Point aPos = GetDrawPosition( Point(mnBaseAdv,0) );
const Fixed nFixedX = Vcl2Fixed( +aPos.X() );
const Fixed nFixedY = Vcl2Fixed( -aPos.Y() ); // adjusted for y-mirroring
- theErr = ATSUDrawText( maATSULayout, mnMinCharPos, mnCharCount, nFixedX, nFixedY );
- DBG_ASSERT( (theErr==noErr), "ATSLayout::DrawText ATSUDrawText failed!\n" );
+ if( maSubPortions.empty() )
+ ATSUDrawText( maATSULayout, mnMinCharPos, mnCharCount, nFixedX, nFixedY );
+ else
+ {
+ // draw the sub-portions and apply individual adjustments
+ SubPortionVector::const_iterator it = maSubPortions.begin();
+ for(; it != maSubPortions.end(); ++it )
+ {
+ const SubPortion& rSubPortion = *it;
+ ATSUDrawText( maATSULayout,
+ rSubPortion.mnMinCharPos, rSubPortion.mnEndCharPos - rSubPortion.mnMinCharPos,
+ nFixedX + rSubPortion.mnXOffset, nFixedY );
+ }
+ }
// request an update of the changed window area
if( rAquaGraphics.IsWindowGraphics() )
@@ -437,6 +456,28 @@ int ATSLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphIDs, Point& rPos, int
Fixed nXOffset = mnBaseAdv;
for( int i = 0; i < nStart; ++i )
nXOffset += mpGlyphAdvances[ i ];
+ // if sub-portion offsets are involved there is an additional x-offset
+ if( !maSubPortions.empty() )
+ {
+ // prepare to find the sub-portion
+ int nCharPos = nStart + mnMinCharPos;
+ if( mpGlyphs2Chars )
+ nCharPos = mpGlyphs2Chars[nStart];
+
+ // find the matching subportion
+ // TODO: is a non-linear search worth it?
+ SubPortionVector::const_iterator it = maSubPortions.begin();
+ for(; it != maSubPortions.end(); ++it) {
+ const SubPortion& r = *it;
+ if( nCharPos < r.mnMinCharPos )
+ continue;
+ if( nCharPos >= r.mnEndCharPos )
+ continue;
+ // apply the sub-portion xoffset
+ nXOffset += r.mnXOffset;
+ break;
+ }
+ }
Fixed nYOffset = 0;
if( mpDeltaY )
@@ -455,7 +496,7 @@ int ATSLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphIDs, Point& rPos, int
// check if glyph fallback is needed for this glyph
// TODO: use ATSUDirectGetLayoutDataArrayPtrFromTextLayout(kATSUDirectDataStyleIndex) API instead?
- const int nCharPos = mpGlyphs2Chars ? mpGlyphs2Chars[nStart] : nStart + mnMinCharPos;
+ const int nCharPos = mpGlyphs2Chars ? mpGlyphs2Chars[nStart] : nStart + mnMinCharPos;
ATSUFontID nFallbackFontID = kATSUInvalidFontID;
UniCharArrayOffset nChangedOffset = 0;
UniCharCount nChangedLength = 0;
@@ -495,6 +536,8 @@ int ATSLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphIDs, Point& rPos, int
break;
// stop when next the x-position is unexpected
+ if( !maSubPortions.empty() )
+ break; // TODO: finish the complete sub-portion
if( !pGlyphAdvances && mpGlyphOrigAdvs )
if( mpGlyphAdvances[nStart-1] != mpGlyphOrigAdvs[nStart-1] )
break;
@@ -616,6 +659,7 @@ long ATSLayout::FillDXArray( long* pDXArray ) const
**/
int ATSLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const
{
+ // get a quick overview on what could fit
const long nPixelWidth = (nMaxWidth - (nCharExtra * mnCharCount)) / nFactor;
UniCharArrayOffset nBreakPos = mnMinCharPos;
@@ -634,6 +678,26 @@ int ATSLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) cons
if( nBreakPos >= static_cast<UniCharArrayOffset>(mnEndCharPos) )
return STRING_LEN;
+ // for the nCharExtra!=0 case the resulting nBreakPos needs be involved
+ if( nCharExtra != 0 )
+ {
+ // age-old nCharExtra!=0 semantic is quite incompatible with ATSUBreakLine()
+ // TODO: use a better way than by testing each the char position
+ InitGIA();
+ ATSUTextMeasurement nATSUSumWidth = 0;
+ const ATSUTextMeasurement nATSUMaxWidth = Vcl2Fixed( nMaxWidth / nFactor );
+ const ATSUTextMeasurement nATSUExtraWidth = Vcl2Fixed( nCharExtra ) / nFactor;
+ for( int i = 0; i < mnCharCount; ++i)
+ {
+ nATSUSumWidth += mpCharWidths[i];
+ if( nATSUSumWidth >= nATSUMaxWidth )
+ return (mnMinCharPos + i);
+ nATSUSumWidth += nATSUExtraWidth;
+ }
+
+ return STRING_LEN;
+ }
+
// GetTextBreak()'s callers expect it to return the "stupid visual line break".
// Returning anything else result.s in subtle problems in the application layers.
static const bool bInWord = true; // TODO: add as argument to GetTextBreak() method
@@ -730,7 +794,7 @@ bool ATSLayout::GetBoundRect( SalGraphics&, Rectangle& rVCLRect ) const
// -----------------------------------------------------------------------
/**
- * ATSLayout::InitGIA() : Get many informations about layouted text
+ * ATSLayout::InitGIA() : get many informations about layouted text
*
* Fills arrays of information about the gylph layout previously done
* in ASTLayout::LayoutText() : glyph advance (width), glyph delta Y (from baseline),
@@ -738,7 +802,7 @@ bool ATSLayout::GetBoundRect( SalGraphics&, Rectangle& rVCLRect ) const
*
* @return : true if everything could be computed, otherwise false
**/
-bool ATSLayout::InitGIA() const
+bool ATSLayout::InitGIA( ImplLayoutArgs* pArgs ) const
{
// no need to run InitGIA more than once on the same ATSLayout object
if( mnGlyphCount >= 0 )
@@ -820,7 +884,53 @@ bool ATSLayout::InitGIA() const
"ATSLayout::InitGIA(): measured widths do not match!\n" );
#endif
- // Release data array ptr
+ // #i91183# we need to split up the portion into sub-portions
+ // if the ATSU-layout differs too much from the requested layout
+ if( pArgs && pArgs->mpDXArray )
+ {
+ // TODO: non-strong-LTR case cases should be handled too
+ if( 0 == (~pArgs->mnFlags & (TEXT_LAYOUT_BIDI_STRONG|TEXT_LAYOUT_BIDI_LTR)) )
+ {
+ Fixed nSumCharWidths = 0;
+ SubPortion aSubPortion = { mnMinCharPos, 0, 0 };
+ for( int i = 0; i < mnCharCount; ++i )
+ {
+ // calculate related logical position
+ nSumCharWidths += mpCharWidths[i];
+
+ // start new sub-portion if needed
+ const Fixed nNextXPos = Vcl2Fixed(pArgs->mpDXArray[i]);
+ const Fixed nNextXOffset = nNextXPos - nSumCharWidths;
+ const Fixed nFixedDiff = aSubPortion.mnXOffset - nNextXOffset;
+ if( (nFixedDiff < -0xC000) || (nFixedDiff > +0xC000) ) {
+ // get to the end of the current sub-portion
+ // prevent splitting up at diacritics etc.
+ int j = i;
+ while( (++j < mnCharCount) && !mpCharWidths[j] );
+ aSubPortion.mnEndCharPos = mnMinCharPos + j;
+ // emit current sub-portion
+ maSubPortions.push_back( aSubPortion );
+ // prepare next sub-portion
+ aSubPortion.mnMinCharPos = aSubPortion.mnEndCharPos;
+ aSubPortion.mnXOffset = nNextXOffset;
+ }
+ }
+
+ // emit the remaining sub-portion
+ if( !maSubPortions.empty() )
+ {
+ aSubPortion.mnEndCharPos = mnEndCharPos;
+ if( aSubPortion.mnEndCharPos != aSubPortion.mnMinCharPos )
+ maSubPortions.push_back( aSubPortion );
+ }
+ }
+
+ // override layouted charwidths with requested charwidths
+ for( int n = 0; n < mnCharCount; ++n )
+ mpCharWidths[ n ] = pArgs->mpDXArray[ n ];
+ }
+
+ // release the ATSU layout records
ATSUDirectReleaseLayoutDataArrayPtr(NULL,
kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&pALR );
@@ -998,84 +1108,10 @@ void PolyArgs::ClosePolygon()
}
#endif
// =======================================================================
-#if 0
-// helper functions for ATSLayout::GetGlyphOutlines()
-OSStatus MyATSCubicMoveToCallback( const Float32Point *pt1,
- void* pData )
-{
- PolyArgs& rA = *reinterpret_cast<PolyArgs*>(pData);
- // MoveTo implies a new polygon => finish old polygon first
- rA.ClosePolygon();
- rA.AddPoint( *pt1, POLY_NORMAL );
-}
-
-OSStatus MyATSCubicLineToCallback( const Float32Point* pt1,
- void* pData )
-{
- PolyArgs& rA = *reinterpret_cast<PolyArgs*>(pData);
- rA.AddPoint( *pt1, POLY_NORMAL );
-}
-
-OSStatus MyATSCubicCurveToCallback( const Float32Point* pt1,
- const Float32Point* pt2, const Float32Point* pt3, void* pData )
-{
- PolyArgs& rA = *reinterpret_cast<PolyArgs*>(pData);
- rA.AddPoint( *pt1, POLY_CONTROL );
- rA.AddPoint( *pt2, POLY_CONTROL );
- rA.AddPoint( *pt3, POLY_NORMAL );
-}
-
-OSStatus MyATSCubicClosePathCallback (
- void *pData )
-{
- PolyArgs& rA = *reinterpret_cast<PolyArgs*>(pData);
- rA.ClosePolygon();
-}
-#endif
-// -----------------------------------------------------------------------
-
-bool ATSLayout::GetGlyphOutlines( SalGraphics&, PolyPolyVector& rPPV ) const
-{
- return false;
-
- /*
- rPPV.clear();
-
- if( !InitGIA() )
- return false;
-
- rPPV.resize( mpGIA->numGlyphs );
- PolyArgs aPolyArgs;
- const ATSUGlyphInfo* pG = mpGIA->glyphs;
- for( int i = 0; i < mpGIA->numGlyphs; ++i, ++pG )
- {
- // convert glyphid at glyphpos to outline
- GlyphID nGlyphId = pG->glyphID;
- long nDeltaY = Float32ToInt( pG->deltaY );
- aPolyArgs.Init( &rPPV[i], pG->screenX, nDeltaY );
- OSStatus nStatus, nCBStatus;
- nStatus = ATSUGlyphGetCubicPaths(
- mrATSUStyle, nGlyphId,
- MyATSCubicMoveToCallback, MyATSCubicLineToCallback,
- MyATSCubicCurveToCallback, MyATSCubicClosePathCallback,
- &aPolyArgs, &nCBStatus );
-
- if( (nStatus != noErr) && (nCBStatus != noErr) )
- {
- fprintf(stderr,"ATSUCallback = %d,%d\n", nStatus, nCBStatus );
- rPPV.resize( i );
- break;
- }
- }
-
- return true;
- */
-}
-
-// -----------------------------------------------------------------------
// glyph fallback is supported directly by Aqua
-// so MultiSalLayout-only methods can be dummy implementated
+// so methods used only by MultiSalLayout can be dummy implementated
+bool ATSLayout::GetGlyphOutlines( SalGraphics&, PolyPolyVector& rPPV ) const { return false; }
void ATSLayout::InitFont() {}
void ATSLayout::MoveGlyph( int /*nStart*/, long /*nNewXPos*/ ) {}
void ATSLayout::DropGlyph( int /*nStart*/ ) {}
diff --git a/vcl/aqua/source/window/salframeview.mm b/vcl/aqua/source/window/salframeview.mm
index 00b91fa66456..11bd3e7dca87 100755
--- a/vcl/aqua/source/window/salframeview.mm
+++ b/vcl/aqua/source/window/salframeview.mm
@@ -36,6 +36,7 @@
#include "salframe.h"
#include "salframeview.h"
#include "aqua11yfactory.h"
+#include <sal/alloca.h>
#include "vcl/window.hxx"
#include "vcl/svapp.hxx"
@@ -129,6 +130,23 @@ static const struct ExceptionalKey
{ KEY_D, NSCommandKeyMask | NSShiftKeyMask | NSAlternateKeyMask }
};
+static AquaSalFrame* getMouseContainerFrame()
+{
+ int nWindows = 0;
+ NSCountWindows( &nWindows );
+ int* pWindows = (int*)alloca( nWindows * sizeof(int) );
+ // note: NSWindowList is supposed to be in z-order front to back
+ NSWindowList( nWindows, pWindows );
+ AquaSalFrame* pDispatchFrame = NULL;
+ for(int i = 0; i < nWindows && ! pDispatchFrame; i++ )
+ {
+ NSWindow* pWin = [NSApp windowWithWindowNumber: pWindows[i]];
+ if( pWin && [pWin isMemberOfClass: [SalFrameWindow class]] && [(SalFrameWindow*)pWin containsMouse] )
+ pDispatchFrame = [(SalFrameWindow*)pWin getSalFrame];
+ }
+ return pDispatchFrame;
+}
+
@implementation SalFrameWindow
-(id)initWithSalFrame: (AquaSalFrame*)pFrame
{
@@ -460,10 +478,23 @@ private:
{
// no, it is not
// now we need to find the one it may be in
- // use NSApp to check windows in ZOrder whether they contain the mouse pointer
- NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
- if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
- pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
+ /* #i93756# we ant to get enumerate the application windows in z-order
+ to check if any contains the mouse. This could be elegantly done with this
+ code:
+
+ // use NSApp to check windows in ZOrder whether they contain the mouse pointer
+ NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
+ if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
+ pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
+
+ However if a non SalFrameWindow is on screen (like e.g. the file dialog)
+ it can be hit with the containsMouse selector, which it doesn't support.
+ Sadly NSApplication:makeWindowsPerform does not check (for performance reasons
+ I assume) whether a window supports a selector before sending it.
+ */
+ AquaSalFrame* pMouseFrame = getMouseContainerFrame();
+ if( pMouseFrame )
+ pDispatchFrame = pMouseFrame;
}
}