📄 macroot.cpp
字号:
m_bItsOKToDoAnInterruptBlit = TRUE; Rect dstR; dstR.left = dst.left; dstR.top = dst.top; dstR.right = dst.right; dstR.bottom = dst.bottom; // Forcing the source rect to equal the destination rect; all the // complicated math actually takes place elsewhere so this is an // OK thing to do. Rect srcR = dstR; if (CHXMacSite::zm_bFullScreenActive) { CHXMacSite* pMacSite = (CHXMacSite*)m_pSite; if (!pMacSite->m_bInternalResizeOnFullscreen) { dstR.right = dstR.left + (long)(((double)dstR.right - (double)dstR.left)*pMacSite->m_fStretchMultiple); dstR.bottom = dstR.top + (long)(((double)dstR.bottom - (double)dstR.top)*pMacSite->m_fStretchMultiple); } } if (m_nBlitDepthEnum >= 0) { RGBColor blackRGB = {0x0000, 0x0000, 0x0000}; RGBColor whiteRGB = {0xffff, 0xffff, 0xffff}; ColorSpec prevFore; ColorSpec prevBack; ::SaveFore(&prevFore); ::SaveBack(&prevBack); ::RGBForeColor(&blackRGB); ::RGBBackColor(&whiteRGB); ::CopyBits( (BitMap*)*m_RootGWorldPixMap[m_nBlitDepthEnum], GetPortBitMapForCopyBits(GetWindowPort(macWindow)), &srcR, &dstR, srcCopy, nil ); ::QDFlushPortBuffer( ::GetWindowPort(macWindow), NULL ); ::RestoreFore(&prevFore); ::RestoreBack(&prevBack); } SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v); ::SetPort(savePort); }}unsigned longCMacRootSurface::_GetScreenPixelValue(long globX, long globY){ unsigned long retVal = 0; int whichDevice; for (whichDevice = 0; whichDevice < zm_uNumberOfAttachedDevices; whichDevice++) { HX_ASSERT(zm_AttachedDevice[whichDevice]); PixMapHandle thePMH = (**zm_AttachedDevice[whichDevice]).gdPMap; unsigned long dstPtr = (unsigned long)::GetPixBaseAddr(thePMH); int pixelSize = (**thePMH).pixelSize; Rect deviceRect = (**zm_AttachedDevice[whichDevice]).gdRect; if (globX >= deviceRect.left && globX <= deviceRect.right && globY >= deviceRect.top && globY <= deviceRect.bottom) { int rowOffset = (globY - deviceRect.top) * ((**thePMH).rowBytes & 0x3fff); int columnOffset = (globX - deviceRect.left) * pixelSize / 8; dstPtr += rowOffset + columnOffset; switch (pixelSize) { case 32: retVal = *(unsigned long*)dstPtr; break; case 16: retVal = *(unsigned short*)dstPtr; break; case 8: retVal = *(unsigned char*)dstPtr; break; } } } return retVal;}unsigned longCMacRootSurface::_GetGWorldPixelValue(int whichDepth, long x, long y){ unsigned long retVal = 0; unsigned long offscreenPtr = (unsigned long)GetPixBaseAddr(m_RootGWorldPixMap[whichDepth]); offscreenPtr += y * ((**m_RootGWorldPixMap[whichDepth]).rowBytes & 0x3fff); switch (whichDepth) { case kEightBitDepth: offscreenPtr += x; retVal = *(unsigned char*)offscreenPtr; break; case kSixteenBitDepth: offscreenPtr += 2*x; retVal = *(unsigned short*)offscreenPtr; break; case kThirtyTwoBitDepth: offscreenPtr += 4*x; retVal = *(unsigned long*)offscreenPtr; break; } return retVal;}/************************************************************************ * Method: * CMacRootSurface::InternalReflectRect * * Note that theRectToBlit needs to be in global coords! * * This is the function that slams it home. All obscuring menus have * been taken care of. Any vis region holes have been taken care of. * The rectangles that arrive at this rectangle are honest-to-God * blittable rectangles. * */voidCMacRootSurface::InternalReflectRect(Rect theRectToBlit){ int whichDevice; for (whichDevice = 0; whichDevice < zm_uNumberOfAttachedDevices; whichDevice++) { HX_ASSERT(zm_AttachedDevice[whichDevice]); PixMapHandle thePMH = (**zm_AttachedDevice[whichDevice]).gdPMap; unsigned char* dstPtr = (unsigned char*)::GetPixBaseAddr(thePMH); int pixelSize = (**thePMH).pixelSize; INT32 whichDepth = DepthToDepthEnum(pixelSize); if ( 1 /* m_RootSurfaceGWorld[whichDepth] */ ) // <== this may be useful later but for now I want the assert to be executed that's maybe a dozen lines down. { Rect deviceRect = (**zm_AttachedDevice[whichDevice]).gdRect; Rect intersectionRect; // <== should always be equal to theRectToBlit I think XXXbobclark if (::SectRect(&theRectToBlit, &deviceRect, &intersectionRect)) { // XXXbobclark // in the old site code we manually trimmed theRectToBlit to the limits of // intersectionRect; but since nowadays we're supposedly ensuring that we're // only getting rects wholly enclosed by their monitors we shouldn't need // to do that. Theoretically the only reason to do SectRect is to see if // this is actually the monitor that we need to blit to right now. HX_ASSERT(m_RootSurfaceGWorld[whichDepth]); if (!m_RootSurfaceGWorld[whichDepth]) return; unsigned char* offscreenPtr = (unsigned char*)GetPixBaseAddr(m_RootGWorldPixMap[whichDepth]); int localLeft = intersectionRect.left - m_LocalToGlobalCoords.h; int localTop = intersectionRect.top - m_LocalToGlobalCoords.v; int localRight = intersectionRect.right - m_LocalToGlobalCoords.h; int localBottom = intersectionRect.bottom - m_LocalToGlobalCoords.v; int localScreenLeft = intersectionRect.left - (**zm_AttachedDevice[whichDevice]).gdRect.left; int localScreenRight = intersectionRect.right - (**zm_AttachedDevice[whichDevice]).gdRect.left; int localScreenTop = intersectionRect.top - (**zm_AttachedDevice[whichDevice]).gdRect.top; int localScreenBottom = intersectionRect.bottom - (**zm_AttachedDevice[whichDevice]).gdRect.top; for (int localScreenRow = localScreenTop; localScreenRow < localScreenBottom; localScreenRow++) { int bytesPerPixel = pixelSize / 8; if (bytesPerPixel >= 1) // only ITB if at least 8-bit monitor { int localRow = (localScreenRow-localScreenTop) + localTop; long offscreenOffset = ((**m_RootGWorldPixMap[whichDepth]).rowBytes & 0x3fff) * localRow + localLeft * bytesPerPixel; long localScreenOffset = ((**thePMH).rowBytes & 0x3fff) * localScreenRow + localScreenLeft * bytesPerPixel; long srcP = (long)offscreenPtr + offscreenOffset; long dstP = (long)dstPtr + localScreenOffset; switch (bytesPerPixel) { case 4: // XXXbobclark // now we'll trash srcP and dstP... // it turns out that poking longs by hand is a lot faster // than going through BlockMoveData for some reason. In a // simplified test case, it was using 7-8 microseconds for // poking by hand, compared to 17-18 microseconds for using // BlockMoveData. { long maxP = dstP + (localRight-localLeft) * bytesPerPixel; for ( ; dstP < maxP; ) { // if the pixel is lined up on an eight-byte boundary // and won't overwrite the right edge of the rectangle // then copy eight bytes at once. if ( (dstP % 8 == 0) && (maxP - dstP >= 8) ) { *(double*)dstP = *(double*)srcP; srcP += 8; dstP += 8; } else { *(long*)dstP = *(long*)srcP; srcP += 4; dstP += 4; } } } break; default: // XXXbobclark // I could do something similar to the 32-bit case here, // where I attempt to outdo BlockMoveData()... but for // one thing, it would be even clunkier, since I'd need // more cases when it doesn't happen to line up on eight- // byte boundaries for super-fast copies, plus non-32-bit // cases are rarer than 32-bit cases. ::BlockMoveData( (void*)srcP, (void*)dstP, (localRight-localLeft)*bytesPerPixel ); break; } } } } } }}/************************************************************************ * Method: * CMacRootSurface::InternalReflectRectInVisRegion * * Note that theRectToBlit needs to be in global coords! * */voidCMacRootSurface::InternalReflectRectInVisRegion(Rect theRectToBlit){ CHXSimpleList::Iterator ndx = m_pVisRgnRects->Begin(); for (; ndx != m_pVisRgnRects->End(); ++ndx) { Rect* r = (Rect*)(*ndx); Rect blittableRect = theRectToBlit; if (blittableRect.left < r->left) blittableRect.left = r->left; if (blittableRect.top < r->top) blittableRect.top = r->top; if (blittableRect.right > r->right) blittableRect.right = r->right; if (blittableRect.bottom > r->bottom) blittableRect.bottom = r->bottom; if (blittableRect.left < blittableRect.right && blittableRect.top < blittableRect.bottom) { InternalReflectRect(blittableRect); } }}/************************************************************************ * Method: * CMacRootSurface::PotentiallyAddRect * * Useful shortcut for constructing lists of rectangles for * menu-down blitting. * */voidCMacRootSurface::PotentiallyAddRect( CHXSimpleList* theList, Rect originalVisRect, short left, short top, short right, short bottom ){ if ( left < originalVisRect.left ) left = originalVisRect.left; if ( top < originalVisRect.top ) top = originalVisRect.top; if ( right > originalVisRect.right ) right = originalVisRect.right; if ( bottom > originalVisRect.bottom ) bottom = originalVisRect.bottom; if ( left < right && top < bottom ) { // OK, it's a legal rect so let's add it. Rect* r = new Rect; r->left = left; r->top = top; r->right = right; r->bottom = bottom; theList->AddTail( r ); }}/************************************************************************ * Method: * CMacRootSurface::ReflectRectToFullScreen * * Note that theOriginalRectToBlit needs to be in global coords! * */voidCMacRootSurface::ReflectRectToFullScreen(Rect theOriginalRectToBlit){ // xxxbobclark assumptions include that this rectangle // is smaller than the main screen (which is where it // assumes the full-screen is playing). // See InternalReflectRect for details of what up HX_ASSERT(CHXMacSite::zm_bFullScreenActive); int whichDevice; for (whichDevice = 0; whichDevice < zm_uNumberOfAttachedDevices; whichDevice++) { PixMapHandle thePMH = (**zm_AttachedDevice[whichDevice]).gdPMap; unsigned char* dstPtr = (unsigned char*)::GetPixBaseAddr(thePMH); int honestScreenRowBytes = (**thePMH).rowBytes & 0x3fff; int pixelSize = (**thePMH).pixelSize; INT32 whichDepth = DepthToDepthEnum(pixelSize); if (m_RootSurfaceGWorld[whichDepth]) { Rect adjustedRect; CHXMacSite* pMacSite = (CHXMacSite*)m_pSite; double stretch = pMacSite->m_fStretchMultiple; adjustedRect.left = theOriginalRectToBlit.left + stretch * (theOriginalRectToBlit.left - m_LocalToGlobalCoords.h); adjustedRect.top = theOriginalRectToBlit.top + stretch * (theOriginalRectToBlit.top - m_LocalToGlobalCoords.v); adjustedRect.right = theOriginalRectToBlit.left + stretch * (theOriginalRectToBlit.right - m_LocalToGlobalCoords.h); adjustedRect.bottom = theOriginalRectToBlit.top + stretch * (theOriginalRectToBlit.bottom - m_LocalToGlobalCoords.v); Rect deviceRect = (**zm_AttachedDevice[whichDevice]).gdRect; if (adjustedRect.left >= deviceRect.left && adjustedRect.top >= deviceRect.top && adjustedRect.right <= deviceRect.right && adjustedRect.bottom <= deviceRect.bottom) { // xxxbobclark whew, we can blit here since it's full // screen and wholly enclosed. int bytesPerPixel = pixelSize / 8; if (bytesPerPixel < 1) return; // ack, can't handle less than 8-bit! unsigned char* offscreenPtr = (unsigned char*)GetPixBaseAddr(m_RootGWorldPixMap[whichDepth]); int honestOffscreenRowBytes = (**m_RootGWorldPixMap[whichDepth]).rowBytes & 0x3fff; int fromLeft = theOriginalRectToBlit.left - m_LocalToGlobalCoords.h; int fromTop = theOriginalRectToBlit.top - m_LocalToGlobalCoords.v; int fromRight = theOriginalRectToBlit.right - m_LocalToGlobalCoords.h; int fromBottom = theOriginalRectToBlit.bottom - m_LocalToGlobalCoords.v; for (int fromRow = fromTop; fromRow < fromBottom; fromRow++) { for (int fromColumn = fromLeft; fromColumn < fromRight; fromColumn++) { // xxxbobclark OK now here we have one pixel // in the offscreen. This could grow to // multiple pixels on screen so we'll have to // blit all of them. long* pixelPtr = (long*)((long)offscreenPtr + fromRow*(long)honestOffscreenRowBytes); pixelPtr = (long*)((long)pixelPtr + bytesPerPixel * fromColumn); long pixelValue = *pixelPtr; // ok, got the pixel value, now figure out where all we // need to poke it. int destLeft = (int)((double)(fromColumn - fromLeft) * stretch + (double)adjustedRect.left); int destTop = (int)((double)(fromRow - fromTop) * stretch + (double)adjustedRect.top); int destRight = (int)((double)(fromColumn - fromLeft + 1) * stretch + (double)adjustedRect.left); int destBottom = (int)((double)(fromRow - fromTop + 1) * stretch + (double)adjustedRect.top); pixelPtr = (long*)((long)dstPtr + destTop * honestScreenRowBytes); pixelPtr = (long*)((long)pixelPtr + bytesPerPixel * destLeft); for (int destRow = destTop; destRow < destBottom; destRow++) { for (int destColumn = destLeft; destColumn < destRight; destColumn++) { *pixelPtr = pixelValue; pixelPtr = (long*)((long)pixelPtr + bytesPerPixel); } pixelPtr = (long*)((long)pixelPtr + honestScreenRowBytes - (bytesPerPixel * (destRight-destLeft))); } } } } } }}/************************************************************************ * Method: * CMacRootSurface::DepthToDepthEnum */intCMacRootSurface::DepthToDepthEnum( short depth ){ int result = kEightBitDepth; switch ( depth ) { case 32: result = kThirtyTwoBitDepth; break; case 16: result = kSixteenBitDepth; break; } return result;}/************************************************************************ * Method: * CMacRootSurface::VisRgnChangedCallback * * This is called from several trap patches which can * change the vis region. This prevents subsequent blits * until the vis region we know about can be updated. *//* static */pascal voidCMacRootSurface::VisRgnChangedCallback(void){#ifndef _MAC_UNIX HXMM_INTERRUPTON();#endif // since the visRgn probably changed in the patched trap, let's wait until // we can update our version of the visRgn before doing any more interrupt- // time blits. CHXSimpleList::Iterator ndxSite = zm_RootSurfaceList.Begin(); for (; ndxSite != zm_RootSurfaceList.End(); ++ndxSite) { CMacRootSurface* pRootSurface = (CMacRootSurface*)(*ndxSite); if ( pRootSurface ) { pRootSurface->m_bItsOKToDoAnInterruptBlit = FALSE; } } if (CMacSurface::zm_pOverlaySurface) { CMacSurface::zm_bSafeToOverlayBlit = FALSE; }#ifndef _MAC_UNIX HXMM_INTERRUPTOFF();#endif}#define kSizeOfSimpleRectangleRegion 10/************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -