diff options
-rw-r--r-- | ios/experimental/TiledLibreOffice/TiledLibreOffice/TiledView.m | 26 | ||||
-rw-r--r-- | vcl/quartz/salgdicommon.cxx | 141 |
2 files changed, 165 insertions, 2 deletions
diff --git a/ios/experimental/TiledLibreOffice/TiledLibreOffice/TiledView.m b/ios/experimental/TiledLibreOffice/TiledLibreOffice/TiledView.m index 80680dd52269..aafbd430682e 100644 --- a/ios/experimental/TiledLibreOffice/TiledLibreOffice/TiledView.m +++ b/ios/experimental/TiledLibreOffice/TiledLibreOffice/TiledView.m @@ -82,6 +82,20 @@ static void updateTilesPerSecond(UILabel *label) } } +static int DBG_DRAW_DELAY = 10; +int DBG_DRAW_ROUNDS = -1; +int DBG_DRAW_COUNTER = 0; +int DBG_DRAW_ROUNDS_MAX = INT_MAX; + +- (void)redraw +{ + DBG_DRAW_ROUNDS++; + DBG_DRAW_COUNTER = 0; + [self setNeedsDisplay]; + if (DBG_DRAW_ROUNDS < DBG_DRAW_ROUNDS_MAX) + [NSTimer scheduledTimerWithTimeInterval:DBG_DRAW_DELAY target:self selector:@selector(redraw) userInfo:nil repeats:NO]; +} + - (id)initWithFrame:(CGRect)frame scale:(CGFloat)scale maxZoom:(int)maxZoom { self = [super initWithFrame:frame]; @@ -93,6 +107,13 @@ static void updateTilesPerSecond(UILabel *label) catl.levelsOfDetailBias = catl.levelsOfDetail - 1; [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateTilesPerSecond) userInfo:nil repeats:YES]; + if (getenv("DRAW_INCREMENTALLY_FROM")) { + DBG_DRAW_ROUNDS = atoi(getenv("DRAW_INCREMENTALLY_FROM")); + if (getenv("DRAW_INCREMENTALLY_DELAY") && + atoi(getenv("DRAW_INCREMENTALLY_DELAY")) > 1) + DBG_DRAW_DELAY = atoi(getenv("DRAW_INCREMENTALLY_DELAY")); + [NSTimer scheduledTimerWithTimeInterval:DBG_DRAW_DELAY target:self selector:@selector(redraw) userInfo:nil repeats:NO]; + } } return self; } @@ -138,12 +159,13 @@ static bool tileMatches(const char *spec, CGRect bb) // as needed at the current zoom levels. I keep thinking about // "pixels" incorrectly. - if (!getenv("DRAW_ONLY_TILE") || tileMatches(getenv("DRAW_ONLY_TILE"), bb)) + if (!getenv("DRAW_ONLY_TILE") || tileMatches(getenv("DRAW_ONLY_TILE"), bb)) { + fprintf(stderr, "+++ rendering to context %p\n", ctx); touch_lo_draw_tile(ctx, tileSize.width, tileSize.height, CGPointMake(bb.origin.x/self.scale, bb.origin.y/self.scale), CGSizeMake(bb.size.width/self.scale, bb.size.height/self.scale)); - else { + } else { CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); CGContextFillRect(ctx, CGRectMake(0, 0, bb.size.width, bb.size.height)); } diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx index 873f18851b8a..8591b633d5c4 100644 --- a/vcl/quartz/salgdicommon.cxx +++ b/vcl/quartz/salgdicommon.cxx @@ -40,6 +40,33 @@ #include <basegfx/range/b2ibox.hxx> #endif +#if defined(IOS) && defined(DBG_UTIL) + +// Variables in TiledView.m +extern int DBG_DRAW_ROUNDS, DBG_DRAW_COUNTER, DBG_DRAW_DEPTH; + +#define DBG_DRAW_OPERATION(s,v) \ + do { \ + if (DBG_DRAW_ROUNDS >= 0) { \ + if (DBG_DRAW_COUNTER++ > DBG_DRAW_ROUNDS) \ + return v; \ + SAL_DEBUG("===> " << s << " " << DBG_DRAW_COUNTER); \ + } \ + } while (false) + +#define DBG_DRAW_OPERATION_EXIT(s) \ + do { \ + if (DBG_DRAW_ROUNDS >= 0) \ + SAL_DEBUG("<=== " << s << " " << DBG_DRAW_COUNTER); \ + } while (false) + +#else + +#define DBG_DRAW_OPERATION(s) /* empty */ +#define DBG_DRAW_OPERATION_EXIT(s) /* empty */ + +#endif + using namespace vcl; typedef std::vector<unsigned char> ByteVector; @@ -539,15 +566,20 @@ bool AquaSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp ) { + DBG_DRAW_OPERATION("drawAlphaBitmap", true); + // An image mask can't have a depth > 8 bits (should be 1 to 8 bits) if( rAlphaBmp.GetBitCount() > 8 ) { + DBG_DRAW_OPERATION_EXIT("drawAlphaBitmap"); return false; } + // are these two tests really necessary? (see vcl/unx/source/gdi/salgdi2.cxx) // horizontal/vertical mirroring not implemented yet if( rTR.mnDestWidth < 0 || rTR.mnDestHeight < 0 ) { + DBG_DRAW_OPERATION_EXIT("drawAlphaBitmap"); return false; } @@ -558,8 +590,10 @@ bool AquaSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, rTR.mnSrcHeight ); if( !xMaskedImage ) { + DBG_DRAW_OPERATION_EXIT("drawAlphaBitmap"); return false; } + if ( CheckContext() ) { const CGRect aDstRect = CGRectMake( rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight); @@ -570,6 +604,8 @@ bool AquaSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, CG_TRACE("CGImageRelease(" << xMaskedImage << ")"); CGImageRelease(xMaskedImage); + + DBG_DRAW_OPERATION_EXIT("drawAlphaBitmap"); return true; } @@ -577,8 +613,13 @@ bool AquaSalGraphics::drawTransformedBitmap( const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY, const SalBitmap& rSrcBitmap, const SalBitmap* pAlphaBmp ) { + DBG_DRAW_OPERATION("drawTransformedBitmap", true); + if( !CheckContext() ) + { + DBG_DRAW_OPERATION_EXIT("drawTransformedBitmap"); return true; + } // get the Quartz image CGImageRef xImage = NULL; @@ -590,7 +631,10 @@ bool AquaSalGraphics::drawTransformedBitmap( else xImage = rSrcSalBmp.CreateWithMask( *pMaskSalBmp, 0, 0, (int)aSize.Width(), (int)aSize.Height() ); if( !xImage ) + { + DBG_DRAW_OPERATION_EXIT("drawTransformedBitmap"); return false; + } // setup the image transformation // using the rNull,rX,rY points as destinations for the (0,0),(0,Width),(Height,0) source points @@ -618,16 +662,22 @@ bool AquaSalGraphics::drawTransformedBitmap( // mark the destination as painted const CGRect aDstRect = CGRectApplyAffineTransform( aSrcRect, aCGMat ); RefreshRect( aDstRect ); + + DBG_DRAW_OPERATION_EXIT("drawTransformedBitmap"); return true; } bool AquaSalGraphics::drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency ) { + DBG_DRAW_OPERATION("drawAlphaRect", true); + if( !CheckContext() ) { + DBG_DRAW_OPERATION_EXIT("drawAlphaRect"); return true; } + // save the current state CG_TRACE( "CGContextSaveGState(" << mrContext << ") " << ++mnContextStackDepth ); CGContextSaveGState( mrContext ); @@ -652,20 +702,27 @@ bool AquaSalGraphics::drawAlphaRect( long nX, long nY, long nWidth, CG_TRACE("CGContextRestoreGState(" << mrContext << ") " << mnContextStackDepth--); CGContextRestoreGState(mrContext); RefreshRect( aRect ); + + DBG_DRAW_OPERATION_EXIT("drawAlphaRect"); return true; } void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ) { + DBG_DRAW_OPERATION("drawBitmap",); + if( !CheckContext() ) { + DBG_DRAW_OPERATION_EXIT("drawBitmap"); return; } + const QuartzSalBitmap& rBitmap = static_cast<const QuartzSalBitmap&>(rSalBitmap); CGImageRef xImage = rBitmap.CreateCroppedImage( (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY, (int)rPosAry.mnSrcWidth, (int)rPosAry.mnSrcHeight ); if( !xImage ) { + DBG_DRAW_OPERATION_EXIT("drawBitmap"); return; } @@ -675,6 +732,8 @@ void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rS CG_TRACE( "CGImageRelease(" << xImage << ")" ); CGImageRelease( xImage ); RefreshRect( aDstRect ); + + DBG_DRAW_OPERATION_EXIT("drawBitmap"); } void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap,SalColor ) @@ -686,16 +745,21 @@ void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rS void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, const SalBitmap& rTransparentBitmap ) { + DBG_DRAW_OPERATION("drawBitmap",); + if( !CheckContext() ) { + DBG_DRAW_OPERATION_EXIT("drawBitmap"); return; } + const QuartzSalBitmap& rBitmap = static_cast<const QuartzSalBitmap&>(rSalBitmap); const QuartzSalBitmap& rMask = static_cast<const QuartzSalBitmap&>(rTransparentBitmap); CGImageRef xMaskedImage( rBitmap.CreateWithMask( rMask, rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ) ); if( !xMaskedImage ) { + DBG_DRAW_OPERATION_EXIT("drawBitmap"); return; } @@ -705,6 +769,8 @@ void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rS CG_TRACE( "CGImageRelease(" << xMaskedImage << ")" ); CGImageRelease( xMaskedImage ); RefreshRect( aDstRect ); + + DBG_DRAW_OPERATION_EXIT("drawBitmap"); } #ifndef IOS @@ -761,17 +827,23 @@ bool AquaSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void AquaSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) { + DBG_DRAW_OPERATION("drawLine",); + if( nX1 == nX2 && nY1 == nY2 ) { // #i109453# platform independent code expects at least one pixel to be drawn drawPixel( nX1, nY1 ); + + DBG_DRAW_OPERATION_EXIT("drawLine"); return; } if( !CheckContext() ) { + DBG_DRAW_OPERATION_EXIT("drawLine"); return; } + CG_TRACE( "CGContextBeginPath(" << mrContext << ")" ); CGContextBeginPath( mrContext ); CG_TRACE( "CGContextMoveToPoint(" << mrContext << "," << static_cast<float>(nX1)+0.5 << "," << static_cast<float>(nY1)+0.5 << ")" ); @@ -784,20 +856,27 @@ void AquaSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) Rectangle aRefreshRect( nX1, nY1, nX2, nY2 ); (void) aRefreshRect; // Is a call to RefreshRect( aRefreshRect ) missing here? + + DBG_DRAW_OPERATION_EXIT("drawLine"); } void AquaSalGraphics::drawMask( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, SalColor nMaskColor ) { + DBG_DRAW_OPERATION("drawMask",); + if( !CheckContext() ) { + DBG_DRAW_OPERATION_EXIT("drawMask"); return; } + const QuartzSalBitmap& rBitmap = static_cast<const QuartzSalBitmap&>(rSalBitmap); CGImageRef xImage = rBitmap.CreateColorMask( rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, nMaskColor ); if( !xImage ) { + DBG_DRAW_OPERATION_EXIT("drawMask"); return; } @@ -807,6 +886,8 @@ void AquaSalGraphics::drawMask( const SalTwoRect& rPosAry, const SalBitmap& rSal CG_TRACE( "CGImageRelease(" << xImage << ")" ); CGImageRelease( xImage ); RefreshRect( aDstRect ); + + DBG_DRAW_OPERATION_EXIT("drawMask"); } void AquaSalGraphics::drawPixel( long nX, long nY ) @@ -828,31 +909,41 @@ bool AquaSalGraphics::drawPolyLine( basegfx::B2DLineJoin eLineJoin, com::sun::star::drawing::LineCap eLineCap) { + DBG_DRAW_OPERATION("drawPolyLine", true); + // short circuit if there is nothing to do const int nPointCount = rPolyLine.count(); if( nPointCount <= 0 ) { + DBG_DRAW_OPERATION_EXIT("drawPolyLine"); return true; } + // reject requests that cannot be handled yet if( rLineWidths.getX() != rLineWidths.getY() ) { + DBG_DRAW_OPERATION_EXIT("drawPolyLine"); return false; } + #ifdef IOS if( !CheckContext() ) { + DBG_DRAW_OPERATION_EXIT("drawPolyLine"); return false; } #endif + // #i101491# Aqua does not support B2DLINEJOIN_NONE; return false to use // the fallback (own geometry preparation) // #i104886# linejoin-mode and thus the above only applies to "fat" lines if( (basegfx::B2DLINEJOIN_NONE == eLineJoin) && (rLineWidths.getX() > 1.3) ) { + DBG_DRAW_OPERATION_EXIT("drawPolyLine"); return false; } + // setup line attributes CGLineJoin aCGLineJoin = kCGLineJoinMiter; switch( eLineJoin ) @@ -922,6 +1013,7 @@ bool AquaSalGraphics::drawPolyLine( CG_TRACE( "CGPathRelease(" << xPath << ")" ); CGPathRelease( xPath ); + DBG_DRAW_OPERATION_EXIT("drawPolyLine"); return true; } @@ -933,17 +1025,23 @@ bool AquaSalGraphics::drawPolyLineBezier( sal_uInt32, const SalPoint*, const sal bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency ) { + DBG_DRAW_OPERATION("drawPolyPolygon", true); + // short circuit if there is nothing to do const int nPolyCount = rPolyPoly.count(); if( nPolyCount <= 0 ) { + DBG_DRAW_OPERATION_EXIT("drawPolyPolygon"); return true; } + // ignore invisible polygons if( (fTransparency >= 1.0) || (fTransparency < 0) ) { + DBG_DRAW_OPERATION_EXIT("drawPolyPolygon"); return true; } + // setup poly-polygon path CGMutablePathRef xPath = CGPathCreateMutable(); CG_TRACE( "CGPathCreateMutable() = " << xPath ); @@ -954,6 +1052,7 @@ bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPol } const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); + CG_TRACE( "CGPathGetBoundingBox(" << xPath << ") = " << aRefreshRect ); // #i97317# workaround for Quartz having problems with drawing small polygons if( ! ((aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125)) ) { @@ -976,6 +1075,7 @@ bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPol SAL_WARN( "vcl.quartz", "Neither pen nor brush visible" ); CG_TRACE( "CGPathRelease(" << xPath << ")" ); CGPathRelease( xPath ); + DBG_DRAW_OPERATION_EXIT("drawPolyPolygon"); return true; } @@ -1003,15 +1103,25 @@ bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPol CG_TRACE( "CGPathRelease(" << xPath << ")" ); CGPathRelease( xPath ); + DBG_DRAW_OPERATION_EXIT("drawPolyPolygon"); return true; } void AquaSalGraphics::drawPolyPolygon( sal_uInt32 nPolyCount, const sal_uInt32 *pPoints, PCONSTSALPOINT *ppPtAry ) { + DBG_DRAW_OPERATION("drawPolyPolygon",); + if( nPolyCount <= 0 ) + { + DBG_DRAW_OPERATION_EXIT("drawPolyPolygon"); return; + } + if( !CheckContext() ) + { + DBG_DRAW_OPERATION_EXIT("drawPolyPolygon"); return; + } // find bound rect long leftX = 0, topY = 0, maxWidth = 0, maxHeight = 0; @@ -1056,8 +1166,11 @@ void AquaSalGraphics::drawPolyPolygon( sal_uInt32 nPolyCount, const sal_uInt32 * } else { + SAL_WARN( "vcl.quartz", "Neither pen nor brush visible" ); + DBG_DRAW_OPERATION_EXIT("drawPolyPolygon"); return; } + // convert to CGPath CG_TRACE( "CGContextBeginPath(" << mrContext << ")" ); CGContextBeginPath( mrContext ); @@ -1117,14 +1230,25 @@ void AquaSalGraphics::drawPolyPolygon( sal_uInt32 nPolyCount, const sal_uInt32 * CGContextDrawPath( mrContext, eMode ); RefreshRect( leftX, topY, maxWidth, maxHeight ); + + DBG_DRAW_OPERATION_EXIT("drawPolyPolygon"); } void AquaSalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint *pPtAry ) { + DBG_DRAW_OPERATION("drawPolygon",); + if( nPoints <= 1 ) + { + DBG_DRAW_OPERATION_EXIT("drawPolygon"); return; + } + if( !CheckContext() ) + { + DBG_DRAW_OPERATION_EXIT("drawPolygon"); return; + } long nX = 0, nY = 0, nWidth = 0, nHeight = 0; getBoundRect( nPoints, pPtAry, nX, nY, nWidth, nHeight ); @@ -1144,8 +1268,10 @@ void AquaSalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint *pPtAry ) } else { + SAL_WARN( "vcl.quartz", "Neither pen nor brush visible" ); return; } + CG_TRACE( "CGContextBeginPath(" << mrContext << ")" ); CGContextBeginPath( mrContext ); @@ -1180,6 +1306,8 @@ void AquaSalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint *pPtAry ) CG_TRACE( "CGContextDrawPath(" << mrContext << "," << eMode << ")" ); CGContextDrawPath( mrContext, eMode ); RefreshRect( nX, nY, nWidth, nHeight ); + + DBG_DRAW_OPERATION_EXIT("drawPolygon"); } bool AquaSalGraphics::drawPolygonBezier( sal_uInt32, const SalPoint*, const sal_uInt8* ) @@ -1195,10 +1323,14 @@ bool AquaSalGraphics::drawPolyPolygonBezier( sal_uInt32, const sal_uInt32*, void AquaSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) { + DBG_DRAW_OPERATION("drawRect",); + if( !CheckContext() ) { + DBG_DRAW_OPERATION_EXIT("drawRect"); return; } + CGRect aRect( CGRectMake(nX, nY, nWidth, nHeight) ); if( IsPenVisible() ) { @@ -1219,16 +1351,23 @@ void AquaSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) CGContextStrokeRect( mrContext, aRect ); } RefreshRect( nX, nY, nWidth, nHeight ); + + DBG_DRAW_OPERATION_EXIT("drawRect"); } void AquaSalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry ) { + DBG_DRAW_OPERATION("drawPolyLine",); + if( nPoints < 1 ) { + DBG_DRAW_OPERATION_EXIT("drawPolyLine"); return; } + if( !CheckContext() ) { + DBG_DRAW_OPERATION_EXIT("drawPolyLine"); return; } @@ -1252,6 +1391,8 @@ void AquaSalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry ) CGContextDrawPath( mrContext, kCGPathStroke ); RefreshRect( nX, nY, nWidth, nHeight ); + + DBG_DRAW_OPERATION_EXIT("drawPolyLine"); } sal_uInt16 AquaSalGraphics::GetBitCount() const |