From f7505e1446686d15cfed313b1d20f9cd0408b5a2 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 15 Mar 2006 23:20:20 +0000 Subject: Squelch [Bug 1409140] by special-case-ing the single-pixel put case. Also take better advantage of C's casting rules w.r.t. void* and other pointers --- ChangeLog | 80 +++++++++++++++++++++------------------ generic/tkImgPhoto.c | 103 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 112 insertions(+), 71 deletions(-) diff --git a/ChangeLog b/ChangeLog index 56112e3..c1e594b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2006-03-15 Donal K. Fellows + + * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock): Try + to squelch performance issue with code that writes to large images by + single pixels. Masses of thanks to George Staplin for helping to trace + this down to the COMPLEX_ALPHA flag handling code. [Bug 1409140] + 006-03-13 Don Porter * tests/scrollbar.test: Corrected several broken calls to [testmetrics] @@ -7,24 +14,24 @@ * tests/canvPs.test: to stop test suite crash on Mac OSX. [Bug 1088807] - * generic/tkCmds.c: Purged remaining references to - * macosx/tkMacOSXPort.h: errno, and errno.h. Standardized - * macosx/tkMacOSXWm.c: the logic for using header files from - * macosx/tkMacOSXWm.h: the compat directory. Thanks Joe - * unix/tkUnixPort.h: English for the patch. [Patch 1445404] + * generic/tkCmds.c: Purged remaining references to errno, + * macosx/tkMacOSXPort.h: and errno.h. Standardized the logic + * macosx/tkMacOSXWm.c: for using header files from the compat + * macosx/tkMacOSXWm.h: directory. Thanks Joe English for the + * unix/tkUnixPort.h: patch. [Patch 1445404] 2006-03-08 Don Porter - * unix/Makefile.in: Update `make dist` to copy the image files - needed by the test suite into the source distro. This was overlooked - in the 2005-10-12 commit. + * unix/Makefile.in: Update `make dist` to copy the image files needed + by the test suite into the source distro. This was overlooked in the + 2005-10-12 commit. * changes: Update in prep. for 8.5a4 release. 2006-03-07 Joe English - * unix/tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, - as per the other *BSD variants [Bug 1334613]. + * unix/tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, as per the + other *BSD variants [Bug 1334613]. * unix/configure: Regenerated. 2006-03-07 Donal K. Fellows @@ -52,11 +59,11 @@ 2006-02-09 Daniel Steffen * generic/tk.decls: fix signature of TkMacOSXInvalClipRgns - * generic/tkPlatDecls.h: to use Tk_Window instead of internal - * macosx/tkMacOSXSubwindows.c: type TkWindow (which led to any include + * generic/tkPlatDecls.h: to use Tk_Window instead of internal + * macosx/tkMacOSXSubwindows.c: type TkWindow (which led to any include * macosx/tkMacOSXWindowEvent.c: of public header tkMacOSX.h requiring * macosx/tkMacOSXWm.c: prior include of tkInt.h). - + * generic/tk.h: move TkAqua specific REDO_KEYSYM_LOOKUP define * macosx/tkMacOSXPort.h: out of tk.h into platform header. @@ -181,9 +188,9 @@ 2005-12-09 Daniel Steffen - * generic/tkInt.decls: move all platform test sources from tk lib into - * generic/tkTest.c: tktest directly, removes requirement to export - * macosx/tkMacOSXTest.c: TkplatformtestInit from internal stubs table. + * generic/tkInt.decls: Move all platform test sources from tk lib into + * generic/tkTest.c: tktest directly, removes requirement to export + * macosx/tkMacOSXTest.c:TkplatformtestInit from internal stubs table. * unix/Makefile.in: * win/Makefile.in: * win/makefile.vc: @@ -205,17 +212,17 @@ * win/rc/wish.exe.manifest (removed): and VERSION to be correct. * unix/Makefile.in: fix dist target for manifest dir change - * generic/tkTextTag.c (TkTextTagCmd): use correct arraySize for - peered text widgets in [$text tag names]. [Bug 1375069 1374935] + * generic/tkTextTag.c (TkTextTagCmd): use correct arraySize for peered + text widgets in [$text tag names]. [Bug 1375069 1374935] 2005-12-08 Daniel Steffen - * macosx/tkMacOSXDraw.c: remove inclusion of tclInt.h and use of tcl - * macosx/tkMacOSXFont.c: internals wherever possible in tk/macosx, the - * macosx/tkMacOSXInit.c: only remaining tcl internals in TkAqua are - * macosx/tkMacOSXNotify.c: TclServiceIdle() in tkMacOSXScrlbr.c and - * macosx/tkMacOSXScrlbr.c: Tcl_Get/SetStartupScript() in tkMacOSXInit.c - [RFE 1336531]. + * macosx/tkMacOSXDraw.c: Remove inclusion of tclInt.h and use of tcl + * macosx/tkMacOSXFont.c: internals wherever possible in tk/macosx, the + * macosx/tkMacOSXInit.c: only remaining tcl internals in TkAqua are + * macosx/tkMacOSXNotify.c:TclServiceIdle() in tkMacOSXScrlbr.c and + * macosx/tkMacOSXScrlbr.c:Tcl_Get/SetStartupScript() in tkMacOSXInit.c + [RFE 1336531]. * macosx/tkMacOSXInt.h: sync comments with core-8-4-branch. @@ -462,8 +469,8 @@ 2005-11-15 Joe English - * unix/tkUnixWm.c, tests/unixWm.test, doc/wm.n: - Support for [wm attributes] on X11 [TIP#231, Patch 1062022]. + * unix/tkUnixWm.c, tests/unixWm.test, doc/wm.n: Support for [wm + attributes] on X11 [TIP#231, Patch 1062022]. 2005-11-14 Joe English @@ -477,9 +484,9 @@ 2005-11-13 Donal K. Fellows - * unix/tkUnixSelect.c (SelCvtToX): Arrange for the parsing code to - use Tcl's list parsing code, another simplification that enables - testing of the [Bug 1353414] fix. + * unix/tkUnixSelect.c (SelCvtToX): Arrange for the parsing code to use + Tcl's list parsing code, another simplification that enables testing + of the [Bug 1353414] fix. * unix/tkUnixSelect.c (SelCvtFromX): Generate string forms of the advanced selection types in a Tcl_DString. This makes fixing [Bug @@ -512,20 +519,19 @@ 2005-10-18 Don Porter - * generic/tkMain.c: Rewrote code that sets the ::argv value - to be sure conversion from the system encoding is complete before - any processing sensitive to list-special characters is done. - [Bug 1328926]. + * generic/tkMain.c: Rewrote code that sets the ::argv value to be sure + conversion from the system encoding is complete before any processing + sensitive to list-special characters is done. [Bug 1328926]. 2005-10-17 Jeff Hobbs - * macosx/tkMacOSXScrlbr.c (UpdateControlValues): check geomMgrPtr - is valid before checking type + * macosx/tkMacOSXScrlbr.c (UpdateControlValues): check geomMgrPtr is + valid before checking type 2005-10-15 Jeff Hobbs - * library/menu.tcl (::tk::MenuUnpost): remove leftover ] from - string equal mods of 2005-07-25. (sowadsky) + * library/menu.tcl (::tk::MenuUnpost): remove leftover ] from string + equal mods of 2005-07-25. (sowadsky) 2005-10-14 Pat Thoyts diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 2e890d0..62c2192 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -17,7 +17,7 @@ * Department of Computer Science, * Australian National University. * - * RCS: @(#) $Id: tkImgPhoto.c,v 1.60 2005/11/27 02:36:13 das Exp $ + * RCS: @(#) $Id: tkImgPhoto.c,v 1.61 2006/03/15 23:20:27 dkf Exp $ */ #include "tkInt.h" @@ -495,6 +495,7 @@ PhotoFormatThreadExitProc( * *---------------------------------------------------------------------- */ + void Tk_CreateOldPhotoImageFormat( Tk_PhotoImageFormat *formatPtr) @@ -586,7 +587,7 @@ ImgPhotoCreate( */ masterPtr = (PhotoMaster *) ckalloc(sizeof(PhotoMaster)); - memset((void *) masterPtr, 0, sizeof(PhotoMaster)); + memset(masterPtr, 0, sizeof(PhotoMaster)); masterPtr->tkMaster = master; masterPtr->interp = interp; masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd, @@ -783,7 +784,7 @@ ImgPhotoCmd( */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.zoomX = options.zoomY = 1; options.subsampleX = options.subsampleY = 1; options.name = NULL; @@ -889,7 +890,7 @@ ImgPhotoCmd( Tk_ImageStringWriteProc *stringWriteProc = NULL; index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; options.fromX = 0; @@ -986,7 +987,7 @@ ImgPhotoCmd( result = ((int (*) (Tcl_Interp *interp, Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr, - VOID *dummy)) stringWriteProc) + void *dummy)) stringWriteProc) (interp, options.format, &block, NULL); } if (options.background) { @@ -1037,7 +1038,7 @@ ImgPhotoCmd( */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT, &index, objc, objv) != TCL_OK) { @@ -1209,7 +1210,7 @@ ImgPhotoCmd( */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; if (ParseSubcommandOptions(&options, interp, @@ -1430,20 +1431,24 @@ ImgPhotoCmd( /* * Make pixel transparent. */ + TkRegion clearRegion = TkCreateRegion(); TkUnionRectWithRegion(&setBox, clearRegion, clearRegion); TkSubtractRegion(masterPtr->validRegion, clearRegion, masterPtr->validRegion); TkDestroyRegion(clearRegion); + /* * Set the alpha value correctly. */ + pixelPtr[3] = 0; } else { /* * Make pixel opaque. */ + TkUnionRectWithRegion(&setBox, masterPtr->validRegion, masterPtr->validRegion); pixelPtr[3] = 255; @@ -1483,7 +1488,7 @@ ImgPhotoCmd( */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; if (ParseSubcommandOptions(&options, interp, @@ -2040,9 +2045,11 @@ ImgPhotoConfigureMaster( if (chan == NULL) { goto errorExit; } + /* * -translation binary also sets -encoding binary */ + if ((Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) || (MatchFileFormat(interp, chan, masterPtr->fileString, @@ -3061,15 +3068,14 @@ ImgPhotoSetSize( if ((masterPtr->pix32 != NULL) && ((width == masterPtr->width) || (width == validBox.width))) { if (validBox.y > 0) { - memset((VOID *) newPix32, 0, (size_t) (validBox.y * pitch)); + memset(newPix32, 0, (size_t) (validBox.y * pitch)); } h = validBox.y + validBox.height; if (h < height) { - memset((VOID *) (newPix32 + h * pitch), 0, - (size_t) ((height - h) * pitch)); + memset(newPix32 + h*pitch, 0, (size_t) ((height - h) * pitch)); } } else { - memset((VOID *) newPix32, 0, (size_t) (height * pitch)); + memset(newPix32, 0, (size_t) (height * pitch)); } if (masterPtr->pix32 != NULL) { @@ -3085,8 +3091,7 @@ ImgPhotoSetSize( */ offset = validBox.y * pitch; - memcpy((VOID *) (newPix32 + offset), - (VOID *) (masterPtr->pix32 + offset), + memcpy(newPix32 + offset, masterPtr->pix32 + offset, (size_t) (validBox.height * pitch)); } else if ((validBox.width > 0) && (validBox.height > 0)) { @@ -3098,8 +3103,7 @@ ImgPhotoSetSize( srcPtr = masterPtr->pix32 + (validBox.y * masterPtr->width + validBox.x) * 4; for (h = validBox.height; h > 0; h--) { - memcpy((VOID *) destPtr, (VOID *) srcPtr, - (size_t) (validBox.width * 4)); + memcpy(destPtr, srcPtr, (size_t) (validBox.width * 4)); destPtr += width * 4; srcPtr += masterPtr->width * 4; } @@ -3233,17 +3237,17 @@ ImgPhotoInstanceSetSize( && ((instancePtr->width == masterPtr->width) || (validBox.width == masterPtr->width))) { if (validBox.y > 0) { - memset((VOID *) newError, 0, (size_t) + memset(newError, 0, (size_t) validBox.y * masterPtr->width * 3 * sizeof(schar)); } h = validBox.y + validBox.height; if (h < masterPtr->height) { - memset((VOID *) (newError + h * masterPtr->width * 3), 0, + memset(newError + h*masterPtr->width*3, 0, (size_t) (masterPtr->height - h) * masterPtr->width * 3 * sizeof(schar)); } } else { - memset((VOID *) newError, 0, (size_t) + memset(newError, 0, (size_t) masterPtr->height * masterPtr->width *3*sizeof(schar)); } } else { @@ -3258,8 +3262,7 @@ ImgPhotoInstanceSetSize( if (masterPtr->width == instancePtr->width) { offset = validBox.y * masterPtr->width * 3; - memcpy((VOID *) (newError + offset), - (VOID *) (instancePtr->error + offset), + memcpy(newError + offset, instancePtr->error + offset, (size_t) (validBox.height * masterPtr->width * 3 * sizeof(schar))); @@ -3270,7 +3273,7 @@ ImgPhotoInstanceSetSize( (validBox.y * instancePtr->width + validBox.x) * 3; for (h = validBox.height; h > 0; --h) { - memcpy((VOID *) errDestPtr, (VOID *) errSrcPtr, + memcpy(errDestPtr, errSrcPtr, validBox.width * 3 * sizeof(schar)); errDestPtr += masterPtr->width * 3; errSrcPtr += instancePtr->width * 3; @@ -3435,7 +3438,7 @@ GetColorTable( * Look for an existing ColorTable in the hash table. */ - memset((VOID *) &id, 0, sizeof(id)); + memset(&id, 0, sizeof(id)); id.display = instancePtr->display; id.colormap = instancePtr->colormap; id.palette = instancePtr->palette; @@ -3469,7 +3472,7 @@ GetColorTable( * in imgPhotoColorHash, and can result in core dumps. */ - memset((VOID *) &colorPtr->id, 0, sizeof(ColorTableId)); + memset(&colorPtr->id, 0, sizeof(ColorTableId)); colorPtr->id = id; Tk_PreserveColormap(colorPtr->id.display, colorPtr->id.colormap); colorPtr->flags = 0; @@ -3699,6 +3702,7 @@ AllocateColors( /* * Still can't allocate the color. */ + break; } } @@ -4418,8 +4422,7 @@ Tk_PhotoPutBlock( && ((height == 1) || ((x == 0) && (width == masterPtr->width) && (blockPtr->pitch == pitch))) && (compRule == TK_PHOTO_COMPOSITE_SET)) { - memcpy((VOID *) destLinePtr, - (VOID *) (blockPtr->pixelPtr + blockPtr->offset[0]), + memcpy(destLinePtr, blockPtr->pixelPtr + blockPtr->offset[0], (size_t) (height * width * 4)); /* @@ -4449,8 +4452,7 @@ Tk_PhotoPutBlock( && (blueOffset == 2) && (alphaOffset == 3) && (width <= blockPtr->width) && (compRule == TK_PHOTO_COMPOSITE_SET)) { - memcpy((VOID *) destLinePtr, (VOID *) srcLinePtr, - (size_t) (width * 4)); + memcpy(destLinePtr, srcLinePtr, (size_t) (width * 4)); srcLinePtr += blockPtr->pitch; destLinePtr += pitch; continue; @@ -4599,7 +4601,24 @@ Tk_PhotoPutBlock( */ if (alphaOffset != 0 || masterPtr->flags & COMPLEX_ALPHA) { - ToggleComplexAlphaIfNeeded(masterPtr); + /* + * Note that we skip in the single pixel case if we can. This speeds + * up code that builds up large simple-alpha images by single pixels, + * which seems to be a common use-case. [Bug 1409140] + */ + + if (width == 1 && height == 1 && !(masterPtr->flags & COMPLEX_ALPHA)) { + unsigned char newAlpha; + + destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; + newAlpha = destLinePtr[3]; + + if (newAlpha > 0 && newAlpha < 255) { + masterPtr->flags |= COMPLEX_ALPHA; + } + } else { + ToggleComplexAlphaIfNeeded(masterPtr); + } } /* @@ -4842,7 +4861,6 @@ Tk_PhotoPutZoomedBlock( */ if (alphaOffset) { - if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) { /* * Don't need this when using the OVERLAY compositing rule, which @@ -4861,7 +4879,7 @@ Tk_PhotoPutZoomedBlock( TkDestroyRegion(workRgn); } - TkpBuildRegionFromAlphaData(masterPtr->validRegion, x, y, width, height, + TkpBuildRegionFromAlphaData(masterPtr->validRegion, x,y, width,height, &masterPtr->pix32[(y * masterPtr->width + x) * 4 + 3], 4, masterPtr->width * 4); } else { @@ -4878,7 +4896,24 @@ Tk_PhotoPutZoomedBlock( */ if (alphaOffset != 0 || masterPtr->flags & COMPLEX_ALPHA) { - ToggleComplexAlphaIfNeeded(masterPtr); + /* + * Note that we skip in the single pixel case if we can. This speeds + * up code that builds up large simple-alpha images by single pixels, + * which seems to be a common use-case. [Bug 1409140] + */ + + if (width == 1 && height == 1 && !(masterPtr->flags & COMPLEX_ALPHA)) { + unsigned char newAlpha; + + destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; + newAlpha = destLinePtr[3]; + + if (newAlpha > 0 && newAlpha < 255) { + masterPtr->flags |= COMPLEX_ALPHA; + } + } else { + ToggleComplexAlphaIfNeeded(masterPtr); + } } /* @@ -5360,12 +5395,12 @@ Tk_PhotoBlank( * arrays for each instance. */ - memset((VOID *) masterPtr->pix32, 0, + memset(masterPtr->pix32, 0, (size_t) (masterPtr->width * masterPtr->height * 4)); for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { if (instancePtr->error) { - memset((VOID *) instancePtr->error, 0, + memset(instancePtr->error, 0, (size_t) (masterPtr->width * masterPtr->height * 3 * sizeof(schar))); } -- cgit v0.12