Documentation Archive Developer
Search

ADC Home > Reference Library > Technical Q&As > QuickTime > Carbon >

Creating Sub GWorlds using QTNewGWorldFromPtr


Q: I use two offscreen GWorlds as sources drawing to a destination window on screen. Everything works great when both source and destination are the same size, but what technique can I use if the destination window is smaller? Specifically, I don't want to shrink the source but would like to select sub-rectangles from within the source.

A: QTNewGWorldFromPtr can be used to create smaller GWorlds which reference larger ones.

OSErr QTNewGWorldFromPtr(
    GWorldPtr      *gw,         /* on return, a pointer
                                   to the offscreen */
    OSType         pixelFormat, /* pixel format for
                                   the new GWorld */
    const Rect     *boundsRect, /* bounds and port
                                   rect for the offscreen
                                   pixel map */
    CTabHandle     cTable,      /* same as the source
                                   GWorld */
    GDHandle       aGDevice,    /* NULL */
    GWorldFlags    flags,       /* 0 */
    void           *baseAddr,   /* adjust this value
                                   to the new origin */
    long           rowBytes );  /* get this value
                                   from the source GWorld */

Adjust the origin by adding (x * pixelSize(in bytes) + y * rowBytes) to the baseAddr of the source GWorlds PixMap, then use this new value as the baseAddr parameter passed into QTNewGWorldFromPtr.

The caller is responsible for passing in a baseAddr that isn't going to change during the lifetime of the returned GWorld, therefore applications should first call LockPixels for the GWorld being used as the source before calling QTNewGWorldFromPtr. Listing 1 illustrates this technique.


Listing 1. CreateNewSubGWorld

 /*
    CreateNewSubGWorld

    This function returns a new GWorld that points to a subset
    of the main source GWorld. It checks that the inSubRect
    rectangle is a true subset of the source GWorlds rectangle,
    otherwise the new GWorld would work in an unpredictable
    fashion. It also locks the source PixMap if it's not
    locked. The source GWorlds PixMap should not be unlocked
    or disposed while the sub-GWorld (which is referencing
    the same pixel data) is in use.

    In        inSrcGWorld  - a pointer to the source GWorld
              inSubRect    - the sub rectangle for the
                             new GWorld

    Out       outSubGWorld - address of a GWorldPtr, returns
                             the new subset GWorld
*/
OSErr CreateNewSubGWorld(GWorldPtr inSrcGWorld,
                         const Rect *inSubRect,
                         GWorldPtr *outSubGWorld)
{
    PixMapHandle hPixMap = NULL;
    long theRowBytes = 0L;
    Ptr theBaseAddr = NULL;
    OSType thePixelFormat;
    UInt32 offset = 0L;
    Rect theSubRect = *inSubRect;
    Rect theSrcRect;

    // sanity checks
    if (NULL == inSrcGWorld || NULL == outSubGWorld)
        return paramErr;
    GetPortBounds(inSrcGWorld, &theSrcRect);
    if (theSubRect.top < theSrcRect.top ||
        theSubRect.left < theSrcRect.left ||
        theSubRect.bottom > theSrcRect.bottom ||
        theSubRect.right > theSrcRect.right) return paramErr;

    // get what we need from the source GWorld
    hPixMap = GetGWorldPixMap(inSrcGWorld);
    if (!(GetPixelsState(hPixMap) && pixelsLocked))
        LockPixels(hPixMap);
    theBaseAddr = GetPixBaseAddr(hPixMap);
    theRowBytes = QTGetPixMapHandleRowBytes(hPixMap);
    thePixelFormat = GETPIXMAPPIXELFORMAT(*hPixMap);

    // calculate the new origin of the pixels -
    // - pixelSize is in bits, so divide by 8
    // to turn it to bytes then modify the base
    // address to point to our new origin
    offset = ((inSubRect->left * (**hPixMap).pixelSize / 8) +
              (inSubRect->top * theRowBytes));
    theBaseAddr += offset;

    // coordinate system normalized 0, 0
    OffsetRect(&theSubRect, -theSubRect.left, -theSubRect.top);

    return QTNewGWorldFromPtr(outSubGWorld,
                              thePixelFormat,
                              &theSubRect,
                              (**hPixMap).pmTable,
                              NULL,
                              0,
                              (void *)theBaseAddr,
                              theRowBytes);
}

References:

Technical Q&A QA1007, "LockPixels and DisposeGWorld with QTNewGWorldFromPtr"


[Mar 20 2001]