TweetFollow Us on Twitter

MACINTOSH C
MACINTOSH C: A Hobbyist's Guide To Programming the Mac OS in C
Version 2.3

© 2000 K. J. Bricknell

Go to Contents

(Chapter 12)

DRAWING WITH QUICKDRAW

A link to the associated demonstration program listing is at the bottom of this page



Mathematical Foundations of QuickDraw

QuickDraw defines the following mathematical constructs which are widely used in its functions and data types:

  • The coordinate plane.

  • The point.

  • The rectangle.

  • The region.

The Coordinate Plane

QuickDraw maintains a global coordinate system for the entire potential drawing space. The screen on which QuickDraw displays images represents a small part of a large global coordinate plane. The global coordinate plane is bounded by the limits of QuickDraw coordinates, which range from -32768 to 32767. The (0,0) origin point of the global coordinate plane is assigned to the upper-left corner of the screen. From there, coordinate values decrease to the left and up and increase to the right and down. Any pixel on the screen can be specified by a vertical coordinate (ordinarily labelled v) and a horizontal coordinate (ordinarily labelled h).

In addition to the global coordinate system, QuickDraw maintains a local coordinate system for every window. The relationship between global and local coordinates is shown at Fig 1.

(Coordinate systems)

Points

The intersection of (imaginary) horizontal and vertical grid lines on the coordinate plane marks a point. There is a distinction between points on the coordinate grid and pixels (the dots which make up the visible image on the screen). Points themselves are dimensionless whereas a pixel is not. As shown at Fig 2, a pixel "hangs" down and to the right of the point by which it is addressed. A pixel thus lies between the infinitely thin lines of the coordinate grid.

(Points and pixels)

The data type for points is Point:

     struct Point
     {
       short v;  // Vertical coordinate.
       short h;  // Horizontal coordinate.
     };
     typedef struct Point Point;
     typedef Point *PointPtr;

Rectangles

Rectangles are used to define active areas on the screen, to assign coordinate systems to graphics entities, and to specify the sizes and locations for various graphics operations. Rectangles, like points, are mathematical entities which have no direct representation on the screen. Just as points are infinitely small, the borders of the rectangle are infinitely thin.

The data type for rectangles is Rect:

     struct Rect 
     {
       short top;
       short left;
       short bottom;
       short right;
     };
     typedef struct Rect Rect;
     typedef Rect *RectPtr;

If the bottom coordinate of a rectangle is equal to or less than the top, or the right coordinate is less than the left, the rectangle is an empty rectangle, that is, one that contains no data.

Regions

One of QuickDraw's most powerful features is to work with regions of arbitrary size, shape and complexity. A region is an arbitrary area, or set of areas, the outline of which is one or more closed loops. A region can be concave or convex, can consist of one connected area or many separate ones, and can even have holes in the middle. In the examples at Fig 3, the region on the left has a hole and the one on the right consists of two unconnected areas.

(Two regions)

The data type for regions is Region:

     struct Region
     {
       unsigned short rgnSize;  // Size in bytes.
       Rect           rgnBBox;  // Enclosing rectangle.
       ...                      // More data if region is not rectangular.
     };
     typedef struct Region Region;
     typedef Region *RgnPtr;
     typedef RgnPtr *RgnHandle;

The rgnSize field contains the size, in bytes, of the region. The maximum size is 64 KB.

The rgnBBox field is a rectangle which completely encloses the region. The simplest region is a rectangle. In this case, the rgnBBox field defines the entire region, and there is no optional region data. For rectangular regions (or empty regions), the rgnSize field contains 10. The data for more complex regions is stored in a proprietary format.

The Graphics Pen, Foreground and Background Colours, Pixel Patterns and Bit Patterns, and Transfer Modes

The Graphics Pen

The metaphorical graphics pen used for drawing lines and shapes in a colour graphics port is rectangular in shape and its size (that is, its height and width) is measured in pixels. Whenever you draw into a graphics port, the characteristics of the graphics pen determine how the drawing looks. Those characteristics are as follows:

  • Pen location, which is specified in local coordinates stored in the pnLoc field of the colour graphics port. The functions Move and MoveTo are used to move the pen to a specified location, and the function GetPen gets the pen's current location.

  • Pen size, which is specified by the width and height (in pixels) stored in the pnSize field of the colour graphics port. The pen's default size is one-by-one pixel; however, PenSize can be used to change the size and shape up to a 32,767-by-32767 pixel square. Note that, if either the width or height is set to 0, the pen does not draw.

  • Pen colour, that is, the colour graphics port's foreground colour.

  • Pen pattern, which defines the pattern that the pen draws with.

  • Pen transfer mode, a Boolean or arithmetic operation which determines how QuickDraw transfers the pen pattern to the pixel map during drawing operations.

  • Pen visibility, which is specified by an integer stored in the pnVis field of the graphics port, indicating whether drawing operations will actually appear. For example, for 0 or negative values, the pen draws with "invisible ink". The functions ShowPen and HidePen are used to change pen visibility.

Getting and Setting the Pen State

The following functions are used to get and set the current pen state:

Function Description
GetPenState Returns, in a PenState structure, the graphics pen's current location, size, transfer mode, and pattern.
SetPenState Using information supplied by a PenState structure, sets the graphics pen's location, size, transfer mode, and pattern.
PenNormal Resets the pen size, transfer mode, and pattern to the state initialised when the colour graphics port was opened.

Foreground and Background Colour

Foreground Colour

The function RGBForecolor is used to assign a requested foreground colour to the rgbFgColor field of the colour graphics port. The pixel value determined by the Color Manager to represent the closest available match for the device is stored in the fgColor field. The colour represented by the pixel value in the fgColor field is the colour actually used as the foreground colour.

If your application uses the Palette Manager, you may also use the Palette Manager function PmForeColor to set the foreground colour.

The foreground colour is used by the graphics pen for drawing lines, framed shapes, and text. The foreground colour is also used by QuickDraw shape painting functions.

Background Colour

The function RGBBackColor is used to assign a requested background colour to the rgbBkColor field of the colour graphics port. The pixel value determined by the Color Manager to represent the closest available match for the device is stored in the bkColor field. The colour represented by the pixel value in the bkColor field is the colour actually used as the background colour.

If your application uses the Palette Manager, you may also use the Palette Manager function PmBackColor to set the background colour.

The background colour is used by QuickDraw erasing functions, and is also used by the ScrollRect function to replace the scrolled pixels.

Pixel Patterns and Bit Patterns

Pixel Patterns

If you wish to draw or paint with a colour pattern, rather than the colour in the colour graphics port's fgColor field, you can assign a pixel pattern to the colour graphics port's pnPixPat field using the function PenPixPat. (Initially, the pixel pattern in the colour graphics port's pnPixPat field is all-"black". When you assign a non-all-"black" pattern, the pattern in the pnPixPat field overrides the foreground colour.)

You define a pixel pattern in a 'ppat' resource. To retrieve the pixel pattern stored in the 'ppat' resource, you use the GetPixPat function. The handle to a pixPat data structure returned by GetPixPat may then be used in a call to PenPixPat to assign the pattern to the pnPixPat field.

Similarly, if you wish to erase with a pixel pattern rather than the background colour, or replace the pixels scrolled by ScrollRect with a pixel pattern rather than the background colour, you can assign a pixel pattern to the colour graphics port's bkPixPat field using the function BackPixPat. (Initially, the pixel pattern in the colour graphics port's bkPixPat field is all-"white". When you assign a non-all-"white" pattern, the pattern in the bkPixPat field overrides the background colour)

In addition to drawing, painting and erasing functions, QuickDraw includes shape filling functions, which may be used to fill a specified shape using a specified pixel pattern. A handle to a pixPat data structure is passed in the thePPat parameter of these functions.

Bit Patterns

After drawing or painting with a pixel pattern, you can return to drawing or painting with the foreground colour by simply restoring the default all-"black" pattern to the pnPixPat field by calling PenPat and passing in the bit pattern contained in the QuickDraw global variable black as follows:

     PenPat(&qd.black);

After erasing with a pixel pattern, you can return to erasing with the background colour by simply restoring the default all-"white" pattern to the bkPixPat field by calling PenPat and passing in the bit pattern contained in the QuickDraw global variable white as follows:

     BackPat(&qd.white);

When you use the PenPat and BackPat functions, QuickDraw constructs a pixel pattern equivalent to the bit pattern, The colour graphics port's current foreground colour is used for the "black" bits in the bit pattern, and the background colour is used for the "white" bits.

The PenPat and BackPat functions may also be used to assign other bit patterns to the pnPixPat and bkPixPat fields of the colour graphics port.

Transfer Modes

The term transfer mode may be considered as a generic term encompassing three different transfer mode types. Each has to do with the way source pixels interact with destination pixels during drawing, painting, erasing, filling, and copying operations. The three types of transfer mode are as follows:

  • Boolean Pattern Mode. Boolean pattern modes apply to line drawing, framing, painting, erasing, and filling operations.

  • Boolean Source Mode. Boolean source modes apply to text drawing and copying operations.

  • Arithmetic Source Mode. Arithmetic source modes apply to drawing (including text drawing), painting, and copying operations.

Boolean Pattern Modes

Pattern modes may be assigned to the pnMode field of the colour graphics port using the PenMode function. The modes are represented by eight constants, each of which relates to a specific Boolean operation (COPY, OR, XOR, and BIC (for bit clear) and their inverse variants.

The effects of these modes are best explained assuming a 1-bit (black-and-white) environment in which the foreground colour is black and the background colour is white. The following lists the pattern modes and describes the effect of source pixels on destination pixels in such an environment.

Pattern Mode Action On Destination Pixel
If source pixel is black If source pixel is white
patCopy Apply foreground colour. Apply background colour.
patOr Apply foreground colour. Leave alone.
patXor Invert. Leave alone.
patBic Apply background colour. Leave alone.
notPatCopy Apply background colour. Apply foreground colour.
notPatOr Leave alone. Force black.
notPatXor Leave alone. Invert.
notPatBic Leave alone. Apply background colour.

These effects are illustrated at Fig 4. Note particularly that patCopy causes the destination pixels to be completely over-written. patCopy is the transfer mode initially assigned to the pnMode field of the colour graphics port.

(Effect of pattern modes)

Boolean Source Modes

Boolean source modes may be assigned to the txMode field of the colour graphics port using the function TextMode, and may be passed as parameters in QuickDraw functions for copying pixel images. The Boolean source modes are the equivalent in text drawing and copying to the Boolean pattern mode used for non-text drawing, painting, filling, and erasing operations.

The relevant constants are srcCopy, srcOr, srcXor, srcBic, notSrcCopy, notSrcOr, notSrcXor, and notSrcBic. In general, for pixel images, you will probably want to use the srcCopy mode (which causes the destination pixels to be overwritten completely) or one of the arithmetic source modes.

Arithmetic Source Modes

Arithmetic source modes may be assigned to both the pnMode and txMode fields of the colour graphics port, and may be passed as parameters in QuickDraw functions for copying pixel images.

Arithmetic source modes perform arithmetic operations on the values of the red, green and blue components of the source and destination pixels. Although rarely used by applications, arithmetic transfer modes produce predictable results on indexed devices because they work with RGB colours rather than with colour table indexes. The arithmetic source modes and their effects in a colour environment are as follows:

Constant Value Description
blend 32 Replace destination pixel with a blend of the source and destination pixel colours. If the destination is a bitmap or 1-bit pixel image, revert to srcCopy mode.
addPin 33 Replace destination pixel with the sum of the source and destination pixel colours up to a maximum allowable value. If the destination is a bitmap or 1-bit pixel image, revert to srcBic mode.
addOver 34 Replace destination pixel with the sum of the source and destination pixel colours, but if the value of the red, green or blue component exceeds 65,536, then subtract 65,536 from that value. If the destination is a bitmap or 1-bit pixel image, revert to srcXor mode.
subPin 35 Replace destination pixel with the difference of the source and destination pixel colours, but not less than a minimum allowable value. If the destination is a bitmap or 1-bit pixel image, revert to srcOr mode.
transparent 36 Replace the source and destination pixel with the source pixel if the source pixel is not equal to the background colour.
addMax 37 Compare the source and destination pixels, and replace the destination pixel with the colour containing the greater saturation of each of the RGB components. If the destination is a bitmap or 1-bit pixel image, revert to srcBic mode.
subOver 38 Replace destination pixel with the difference of the source and destination pixel colours, but if the value of the red, green or blue is less than 0, add the negative result to 65,536. If the destination is a bitmap or 1-bit pixel image, revert to srcXor mode.
adMin 39 Compare the source and destination pixels, and replace the destination pixel with the colour containing the lesser saturation of each of the RGB components. If the destination is a bitmap or 1-bit pixel image, revert to srcOr mode.

Drawing Lines and Framed Shapes

Functions for Drawing Lines

You can move the graphics pen to a specified location, and you can draw lines from that location. Lines are drawn using the current graphics pen size, foreground colour or pen pixel/bit pattern, and pen pattern mode.

Functions for moving the graphics pen and drawing lines are as follows:

Function Description
MoveTo Moves the graphics pen location to the specified location, in local coordinates.
Move Moves the graphics pen a specified distance from its current location.
LineTo Draws a line from the current pen location to the specified location, in local coordinates.
Line Draws a line a specified distance from the graphics pen's current location.

Fig 5 shows a line drawn using one of the system-supplied bit patterns, and with a pen of size 20-by-40 pixels. Note that the pen "hangs" below and to the right of the defining points,

(Line drawn by LineTo or Line)

Functions for Drawing Framed Shapes

Framing a shape draws its outline only, using the current pen size, foreground colour or pen pixel/bit pattern, and pen pattern mode. The interior of the shape in unaffected. Framed shapes are drawn using the current graphics pen size, foreground colour or pen pixel/bit pattern, and pen pattern mode.

Functions for drawing framed shapes are as follows:

Function Description
FrameRect Draws a rectangle, the position and size of which are defined by a Rect structure.
FrameOval Draws an oval, the position and size of which are determined by a bounding rectangle defined by a Rect structure.
FrameRoundRect Draws a rounded rectangle, the position and size of which are determined by a bounding rectangle defined by a Rect structure. Curvature of the corners is defined by ovalWidth and ovalHeight parameters.
FrameArc Draws an arc, the position and size of which are determined by a bounding rectangle defined by a Rect structure. Starting point and arc extent are determined by startAngle and arcAngle parameters.
FramePoly Draws a polygon by "playing back" all the line drawing calls that define it.
FrameRgn Draws an outline around a specified region. The line is drawn just inside the region.

Fig 6 shows various framed shapes drawn with various graphics pen sizes and bit patterns. Note that the bounding rectangles completely enclose the shapes they bound, that is, no pixels extend outside the infinitely thin lines of the bounding rectangle. Note also that the arc is a portion of the circumference of an oval bounded by a pair or radii joining at the oval's centre.

(Framed shapes)

Framed Polygons and Regions

Framed polygons and regions require that you call several functions to create and draw them. You begin by calling a function that collects drawing commands into a definition for the object. You then use drawing functions to define the object before calling a function which signals the end of the object definition. Finally, you use a function which draws the newly-defined object.

Framed Polygons

To define a polygon you must first call OpenPoly and then call LineTo a number of times to create lines from the first vertex to the second, from the second vertex to the third, and so on. You then call ClosePoly, which completes the definition process. After defining a polygon in this way, you can draw the polygon, as a framed polygon, using FramePoly.

Note that, in the framed polygon at Fig 5, the final defining line from the last vertex back to the first vertex was not drawn during the definition process. Note also that, as in all line drawing, FramePoly hangs the pen down and to the right of the infinitely thin lines that define the polygon.

Framed Regions

To define a region, you can use any set of lines or shapes, including other regions, so long as the region's outline consists of one or more closed loops. First, however, you must call NewRgn and OpenRgn. You then use line, shape, or region drawing commands to define the region. When you have finished collecting commands to define the outline of the region, you call CloseRgn. You can then draw the framed region using FrameRegion.

Drawing Painted and Filled Shapes

Painting a shape fills both its outline and its interior with the current foreground colour or graphics pen pixel/bit pattern (that is, the pattern in the pnPixPat field of the colour graphics port). Filling a shape fills both its outline and its interior with a pixel pattern or bit pattern passed in a parameter of the QuickDraw shape filling functions.

Transfer Mode. Painting operations utilise the current graphics pen pattern mode. In filling operations, the transfer mode is invariably the pattern mode patCopy, meaning that the destination pixels are always completely overwritten.

Functions for Painting and Filling Shapes

The following lists the available functions for painting and filling shapes:

Function Description
PaintRect Fills a rectangle with the current foreground colour or graphics pen pixel/ bit pattern.
PaintOval Fills an oval with the current foreground colour or graphics pen pixel/ bit pattern.
PaintRoundRect Fills a round rectangle with the current foreground colour or graphics pen pixel/ bit pattern.
PaintArc Fills a wedge with the current foreground colour or graphics pen pixel/ bit pattern.
PaintPoly Fills a polygon with the current foreground colour or graphics pen pixel/ bit pattern.
PaintRgn Fills a region with the current foreground colour or graphics pen pixel/ bit pattern.
FillRect Fills a rectangle with a specified bit pattern.
FillCRect Fills a rectangle with a specified pixel pattern.
FillOval Fills an oval with a specified bit pattern.
FillCOval Fills an oval with a specified pixel pattern.
FillRoundRect Fills a round rectangle with a specified bit pattern.
FillCRoundRect Fills a round rectangle with a specified pixel pattern.
FillArc Fills a wedge of an oval with a specified bit pattern.
FillCArc Fills a wedge of an oval with a specified pixel pattern.
FillPoly Fills a polygon with a specified bit pattern.
FillCPoly Fills a polygon with a specified pixel pattern.
FillRgn Fills a region with a specified bit pattern.
FillCRgn Fills a region with a specified pixel pattern.

Wedges

The wedges drawn by PaintArc, FillArc, and FillCArc are pie-shaped segments of an oval bounded by a pair of radii joining at the oval's centre. A wedge includes part of the oval's interior. Like the framed arc, wedges are defined by the bounding rectangle that encloses the oval, along with a pair of angles marking the positions of the bounding radii. Fig 7 shows a wedge.

Painted and Filled Polygons and Regions

The general procedure for drawing painted and filled polygons and regions is the same as described for their framed counterparts, above.

Fig 7 shows the polygon as defined for the framed polygon at Fig 6, but this time drawn with one of the polygon painting or filling functions. Note that, although the final defining line from the last vertex back to the first vertex was not drawn, the painting and filling functions complete the polygon (whereas FramePoly did not).

Fig 7 also shows a region comprising two rectangles and an overlapping oval, drawn using PaintRgn. Note that, where two regions overlap, the additional area is added to the region and the overlap is removed from the region.

(Wedge, polygon, and region)

Erasing and Inverting Shapes

Erasing a shape fills both its outline and its interior with the background colour or background pixel/bit pattern (that is, the pattern in the bkPixPat field of the colour graphics port). Inverting a shape simply inverts all the pixels in the shape; for example, all black pixels become white, and vice versa.

Transfer Mode. In erasing operations, the transfer mode is invariably the pattern mode patCopy, meaning that the destination pixels are always completely overwritten.

Functions for Erasing and Inverting Shapes

The following list the available functions for painting and filling shapes:

Function Description
EraseRect Fills a rectangle with the current background colour or pixel/ bit pattern.
EraseOval Fills an oval with the current background colour or pixel/ bit pattern.
EraseRoundRect Fills a round rectangle with the current background colour or pixel/ bit pattern.
EraseArc Fills a wedge with the current background colour or pixel/ bit pattern.
ErasePoly Fills a polygon with the current background colour or pixel/ bit pattern.
EraseRgn Fills a region with the current background colour or pixel/ bit pattern.
InvertRect Inverts all the pixels in a rectangle.
InvertOval Inverts all the pixels in an oval.
InvertRoundRect Inverts all the pixels in a round rectangle.
InvertArc Inverts all the pixels in a wedge.
InvertPoly Inverts all the pixels in a polygon.
InvertRgn Inverts all the pixels in a region.

Drawing Pictures

Your application can record a sequence of QuickDraw drawing operations in a picture and play its image back later. Pictures provide a form of graphic data exchange: one program can draw something that was defined in another program, with great flexibility and without having to know any details about what is being drawn. Fig 8 shows an example of a simple picture containing a filled rectangle, a filled oval, and some text.

(Picture)

The subject of pictures is addressed in more detail at Chapter 13 - Offscreen Graphics Worlds, Pictures, Cursors, and Icons.

Drawing Text

Text is just another form of graphics, as is evidenced by the colour graphics port text-related fields txFont, txFace, txSize, txMode, and spExtra. QuickDraw functions are available for changing the values in these fields.

Setting the Font

The font used to draw text in a graphics port may be set using the function TextFont. TextFont takes a single parameter, of type SInt16, which may be either a predefined constant or a font family ID number. Although predefined constants remain in the header file Fonts.h, their use is now discouraged by Apple.

Fonts are resources, and the font family ID is a resource ID. You can get the font family ID using GetFNum. For example, the following sets the current font to Palatino:

     short fontNum;

     GetFNum("\pPalatino",&fontNum);
     TextFont(fontNum);

If you know the font family ID, you can get its name by calling the Font Manager's GetFontName function. If you do not know either the font family ID or the font name, you can use the Resource Manager's GetIndResource function followed by the GetResInfo function to determine the names and IDs of all available fonts.

Setting and Modifying the Text Style

You use the function TextFace to change the text style, using any combination of the constants bold, italic, underline, outline, shadow, condense, and extend. Some examples of usage are as follows:

     TextFace(bold);                     // Set to bold.
     TextFace(bold | italic);            // Set to bold and italic.)
     TextFace(thePort->txFace | bold);   // Add bold to existing.
     TextFace(thePort->txFace &~ bold);  // Remove bold.
     TextFace(normal);                   // Set to plain.

Setting the Font Size

You use the function TextSize to change the font size in typographical points. A point is approximately 1/72 inch.

Changing the Width of Characters

Widening and narrowing space and non-space characters lets you meet special formatting requirements. You use SpaceExtra to specify the extra pixels to be added to or subtracted from the standard width of the space character. SpaceExtra is ordinarily used in application-defined text-justification functions.

Transfer Mode

The transfer mode initially assigned to the txMode field of the colour graphics port is the Boolean source mode srcOr. This mode causes the colour of the glyph to be determined by the foreground colour and the drawn glyph to completely overwrite the existing pixels. (In this mode only those bits which make up the actual glyph are drawn.)

A glyph is the visual representation of a character.

You should generally use either srcOr or srcBic when drawing text, because all other transfer modes draw the character's background as well as the glyph itself. This can result in the clipping of characters by adjacent characters.

Copying Pixel Images Between Graphics Ports

QuickDraw provides the following three primary image-processing functions:

  • CopyBits, which copies a pixel image to another graphics port, with facilities for:

    • Resizing the image.

    • Modifying the image with transfer modes.

    • Clipping the image to a region.

  • CopyMask, which copies a pixel image to another graphics port, with facilities for:

    • Resizing the image.

    • Modifying the image by passing it through a mask.

  • CopyDeepMask, which combines the effects of CopyBits and CopyMask, allowing you to:

    • Resize the image.

    • Clip the image to a region.

    • Specify a transfer mode.

    • Modify the image by passing it through a mask.
The mask used by CopyMask and CopyDeepMask may be another pixel map whose pixels indicate proportionate weights of the colours for the source and destination pixels.

Coercion of CGrafPtr Data Type to GrafPtr Data Type

The CopyBits, CopyMask, and CopyDeepMask functions date from the era of black-and-white Macintoshes, which is why they expect a pointer to a bitmap, not a pixel map, in their source and destination parameters.

Fig 8 shows the relative locations of the first four bytes of the portBits field in a graphics port and the portPixMap field in a colour graphics port. The portBits field is actually a structure of type BitMap, and the first four bytes of that structure (baseAddr) are a pointer to a bit image. portPixMap is a handle to a PixMap structure, the first four bytes of which are a pointer to the pixel map's image data.

(First 27 bytes of GrafPortr and CGrafPort structures)

When you use CopyBits, CopyMask, and CopyDeepMask to copy pixel images between colour graphics ports, you must coerce each port's CGrafPtr data type to a GrafPtr data type, dereference the portBits fields of each and then pass these "bitmaps" in the source and destination parameters. For example, if your application copies a pixel image from a colour graphics port called, say, myColourPort, you could specify (GrafPtr) myColourPort->portBits in the source parameter.

All this works because:

  • In a CGrafPort structure, the two high bits of the portVersion field are always set. These bits in a GrafPort structure are the two high bits in the portBits.rowBytes field, which are always clear.

  • By looking at these bits, CopyBits, CopyMask, and CopyDeepMask can establish that you have passed the functions a handle to a pixel map rather than the base address of a bitmap.

Using Masks

With CopyMask and CopyDeepMask, you supply a pixel map to act as the copying mask. The values of pixels in the mask act as weights that proportionally select between source and destination pixel values.

On indexed devices, pixel images are always copied using the colour table of the source PixMap structure for source colour information, and using the colour table of the current GDevice structure for destination colour information. The colour table attached to the destination PixMap is ignored.

When the PixMap structure for the mask is 1 bit deep, it has the same effect as a bitmap mask, that is, a black bit in the mask means that the destination pixel will take the colour of the source pixel and a white bit in the mask means that the destination pixel is to retain its current colour. When masks have PixMap structures with pixel depths greater than 1, Colour QuickDraw takes a weighted average between the colours in the source and destination PixMap structures. Within each pixel, the calculation is done in RGB colour, on a colour component basis. As an example, a red mask (that is, one with high values for the red components of all pixels) filters out red values coming from the source pixel image.

Transfer Modes

CopyBits and CopyDeepMask both allow you to specify the transfer mode, which can be either a Boolean source mode or an arithmetic source mode.

The Importance of Foreground and Background Colour

Applying a foreground colour other than black or a background colour other than white to the pixel can produce an unexpected result. For consistent results, you should set the foreground colour to black and the background colour to white before using CopyBits, CopyMask, or CopyDeepMask. (That said, setting foreground and background colours to something other than black or white can achieve some interesting colouration effects.)

Dithering

You can use dithering with CopyBits and CopyDeepMask. Dithering is a technique used by these functions to mix existing colours together to create the illusion of a third colour that may be unavailable on an indexed device, and to improve images that you shrink when copying them from a direct device to an indexed device.

If you specify a destination rectangle that is smaller than the source rectangle when using CopyBits, CopyMask, CopyDeepMask on a direct device, Color QuickDraw automatically uses an averaging technique to produce the destination pixels, maintaining high-quality images when shrinking them. On indexed devices, Color QuickDraw averages these pixels only when you explicitly specify dithering.

You can add dithering to any transfer mode by adding the following constant to the transfer mode:

     ditherCopy = 64  // Add to source mode for dithering.

Copying From Offscreen Graphics Ports

To gracefully display complex images, your application should construct the image in an offscreen graphics world and then use CopyBits to transfer the image to the onscreen graphics port. (Offscreen graphics worlds are addressed at Chapter 13 - Offscreen Graphics Worlds, Pictures, Cursors, and Icons.)

Scrolling Pixels in the Port Rectangle

You can use ScrollRect to scroll the pixels in the port rectangle. ScrollRect takes four parameters: the rectangle to scroll, a horizontal distance to scroll, a vertical distance to scroll, and a region handle. ScrollRect is a special form of CopyBits which copies bits enclosed by a rectangle and stores them within that same rectangle. The vacated area is filled with the current background colour or pixel/bit pattern.

Manipulating Rectangles and Regions

QuickDraw provides many functions for manipulating rectangles and regions. You can use the functions which manipulate rectangles to manipulate any shape based on a rectangle, that is, rounded rectangles, ovals , arcs, and wedges.

For example, you could define a rectangle to bound an oval and then frame the oval. You could then use OffsetRect to move the oval's bounding rectangle downwards. Using the offset bounding rectangle, you could frame a second, connected oval to form a figure eight with the first oval. You could then use that shape to help define a region. You could create a second region, and then use UnionRgn to create a region from the union of the two.

Manipulating Rectangles

The following summarises the functions for manipulating, and performing calculations on, rectangles:

Function Description
EmptyRect Determine whether a rectangle is an empty rectangle.
EqualRect Determine whether two rectangles are equal.
InsetRect Shrinks or expands a rectangle.
OffsetRect Moves a rectangle.
PtInRect Determines whether a pixel is enclosed in a rectangle.
PtToAngle Calculates the angle from the middle of a rectangle to a point.
Pt2Rect Determines the smallest rectangle that encloses two points.
SectRect Determines whether two rectangles intersect.
UnionRect Calculates the smallest rectangle that encloses two rectangles.

Manipulating Regions

The following summarises the functions for manipulating, and performing calculations on, regions:

Function Description
CopyRgn Makes a copy of a region.
DiffRgn Subtracts one region from another.
EmptyRgn Determines whether a region is empty.
EqualRgn Determines whether two regions have identical sizes, shapes, and locations.
InsetRgn Shrinks or expands a region.
OffsetRgn Moves a region.
PtInRgn Determines whether a pixel is within a region.
RectInRgn Determines whether a rectangle intersects a region.
RectRgn Changes the structure of an existing region to that of a rectangle (using a Rect).
SectRgn Calculates the intersection of two regions.
SetEmptyRgn Sets a region to empty.
SetRectRgn Changes the structure of an existing region to that of a rectangle (using coordinates).
UnionRgn Calculates the union of two regions.
XorRgn Calculates the difference between the union and the intersection of two regions.

Manipulating Polygons

You can use OffSetPoly to move a polygon; however, QuickDraw provides no other functions for manipulating polygons.

Scaling Shapes and Regions Within the Same Graphics Port

To scale shapes and regions within the same graphics port, you can use the functions ScalePt, MapPt, MapRect, MapRgn, and MapPoly.

Highlighting

Highlighting is used when selecting and deselecting objects such as text or graphics. TextEdit, for example, uses highlighting to indicate selected text. If the current highlight colour is, for example, blue, TextEdit draws the selected text, then uses InvertRgn to produce a blue background for the text.

The system highlight colour, which can be changed by the user at the Highlight Color item in the Color pane of the Appearance control panel, is stored in a low memory global represented by the symbolic name HiliteRGB. It can be retrieved using LMGetHiliteRGB. You can override the default colour using the function HiliteColor. The current colour is copied to the rgbHiliteColor field of the GrafVars structure, a handle to which is stored in the grafVars field of the colour graphics port structure.

Color QuickDraw implements highlighting by replacing the background colour with the highlight colour. Another low memory global, represented by the symbolic name HiliteMode, contains a byte which represents the current highlight mode. One bit in that byte, represented by the constant pHiliteBit, is used to toggle the background and highlight colours.

Color QuickDraw resets the highlight bit after performing each drawing operation, so your application should always clear the highlight bit immediately before calling InvertRgn (or, indeed, any of the other drawing or image-copying function that uses the patXor or srcXor transfer modes.) The highlight mode can be retrieved and set using LMGetHiliteMode and LMSetHiliteMode, and BitClr may be used to clear the highlight bit:

     UInt8 hiliteMode;
     ...
     hiliteMode = LMGetHiliteMode();
     BitClr(&hiliteMode,pHiliteBit);
     LMSetHiliteMode(hiliteMode);

Another way to use highlighting is to add this constant to the transfer mode you pass in calls to the functions PenMode, CopyBits, CopyDeepMask and TextMode:

     hilite = 50  // Add to source or pattern mode for highlighting.

Drawing Other Graphics Entities

In addition to drawing lines, rectangles, rounded rectangles, ovals, arcs, wedges, polygons and regions, and text, you can also use QuickDraw to draw the following:

  • Cursors, which are 16-by-16 pixel images which map the user's movements of the mouse to relative locations on the screen.

  • Icons, which are images that an object, concept, or message. Icons are stored as resources.
Cursors and Icons are addressed at Chapter 13 - Offscreen Graphics Worlds, Pictures, Cursors, and Icons.)

Saving and Restoring the Graphics Port Drawing State

As stated above, the functions GetPenState and SetPenState are used to save and restore the graphics pen's location, size, transfer mode, and pattern, and PenNormal is used to initialise the pen's size, transfer mode, and pattern.

Typically, an application calls GetPenState at the beginning of a function that changes the pen's location, size, transfer mode, and/or pattern and restores the saved state to the pen on exit from that function. Depending on its requirements, an application might also save and restore the colour graphics port's foreground and background colours, and the text transfer mode, in the same way.

Since the introduction of the Appearance Manager, it has also become necessary to save and restore the pen pixel/bit pattern and background pixel/bit pattern in functions that call the Appearance Manager functions SetThemeBackground, SetThemePen, and/or SetThemeWindowBackground. Recall from Chapter 6 - The Appearance Manager that constants of type ThemeBrush are passed in the inBrush parameter of these Appearance Manager functions and that the value in the inBrush parameter can represent either a colour or a pattern depending on the current appearance. If it is a colour, that colour will be assigned to the relevant field of the graphics port structure, that is, the rgbFgColor or rgbBkColor field. If it is a pattern, that pattern will be assigned to the relevant field of the colour graphics port structure, that is, the pnPixPat or bkPixPat field.

Accordingly, in the era of the Appearance Manager, applications which call SetThemeBackground and/or SetThemePen will need to take measures to save and restore the complete graphics port drawing state and, if required, normalise that state.

Mac OS 8.5 (Appearance Manager Version 1.1) and Later

Appearance Manager 1.1, which was introduced with Mac OS 8.5, introduced the following functions for saving, restoring, and normalising the graphics port drawing state:

Function Description
GetThemeDrawingState Obtains the drawing state of the current graphics port.
SetThemeDrawingState Sets the drawing state of the current graphics port.
NormalizeThemeDrawingState Sets the current graphics port to the default drawing state.
DisposeThemeDrawingState Releases the memory associated with a reference to a graphics port's drawing state. (Note that this memory may also be released by passing true in the inDisposeNow parameter of SetThemeDrawingState.)

Information about the current state of the graphics port is stored in a structure of type ThemeDrawingState. This is a private data structure.

Mac OS 8.1 (Appearance Manager Version 1.0.3) and Earlier

To accommodate versions of the Appearance Manager earlier than Version 1.1, you could establish a data structure as shown in the following example, and provide applications-defined functions for saving the drawing state to, and restoring it from, the fields of such a structure:

     struct drawingEnvironment
     {
       PenState     penLocSizeModePat;   // Pen location, size, mode, pattern.
       RGBColor     requestedForeColour; // rgbFgColor field of colour graphics port.
       RGBColor     requestedBackColour; // rgbBkColor field of colour graphics port.
       SInt16       textTransferMode;    // txMode field of colour graphics port.
       PixPatHandle penPixelPattern;     // pnPixPat field of colour graphics port.
       PixPatHandle backPixelPattern;    // bkPixPat field of colour graphics port.
       Pattern      penBitPattern;       // If pen pixel pattern is a bit pattern.
       Pattern      backBitPattern;      // If background pixel pattern is a bit pattern.
     };
     typedef struct drawingEnvironment drawingEnvironment;

Your function for normalising the drawing environment should:

  • Call PenNormal to initialise the pen location, size, mode, and pattern.

  • Call RGBForeColor and RGBBackColor to set the foreground and background colours to, respectively, black and white.

  • Call TextMode with the Boolean source mode srcOr.

  • Call BakPat with the pattern in the QuickDraw global variable white.


Main QuickDraw Constants, Data Types and Functions

Constants

Boolean Pattern Modes

patCopy     = 8
patOr       = 9
patXor      = 10
patBic      = 11
notPatCopy  = 12
notPatOr    = 13
notPatXor   = 14
notPatBic   = 15

Boolean Source Modes

srcCopy     = 0
srcOr       = 1
srcXor      = 2
srcBic      = 3
notSrcCopy  = 4
notSrcOr    = 5
notSrcXor   = 6
notSrcBic   = 7
ditherCopy  = 64

Arithmetic Transfer Modes

blend        = 32
addPin       = 33
addOver      = 34
subPin       = 35
transparent  = 36
addMax       = 37
subOver      = 38
adMin        = 39
ditherCopy   = 64

Highlighting

hilite      = 50
hiliteBit   = 7
pHiliteBit  = 0

Pattern List Resource ID for Pattern Resources in the System File

sysPatListID  = 0

Data Types

typedef unsigned char PixelType;

Point

struct Point
{
  short  v;
  short  h;
};
typedef struct Point Point;
typedef Point *PointPtr;

Rect

struct Rect 
{
  short  top;
  short  left;
  short  bottom;
  short  right;
};
typedef struct Rect Rect;
typedef Rect *RectPtr;

Region

struct Region
{
  short  rgnSize;
  Rect   rgnBBox;
};
typedef struct Region Region;
typedef Region *RgnPtr, **RgnHandle;

Polygon

struct Polygon
{
  short  polySize;
  Rect   polyBBox;
  Point  polyPoints[1];
};

typedef struct Polygon Polygon;
typedef Polygon *PolyPtr, **PolyHandle;

PenState

struct PenState
{
  Point    pnLoc;
  Point    pnSize;
  short    pnMode;
  Pattern  pnPat;
};
typedef struct PenState PenState;

Functions

Initialising QuickDraw

void  InitGraf(void *globalPtr);

Managing the Graphics Pen

void  HidePen(void);
void  ShowPen(void);
void  GetPen(Point *pt);
void  GetPenState(PenState *pnState);
void  SetPenState(const PenState *pnState);
void  PenSize(short width,short height);
void  PenMode(short mode);
void  PenNormal(void);

Getting and Setting Foreground, Background, and Pixel Colour

void  RGBForeColor(const RGBColor *color);
void  RGBBackColor(const RGBColor *color);
void  GetForeColor(RGBColor *color);
void  GetBackColor(RGBColor *color);
void  GetCPixel(short h,short v,RGBColor *cPix);
void  SetCPixel(short h,short v,const RGBColor *cPix);

Creating and Disposing of Pixel Patterns

PixPatHandle  GetPixPat(short patID);
PixPatHandle  NewPixPat(void);
void          CopyPixPat(PixPatHandle srcPP,PixPatHandle dstPP);
void          MakeRGBPat(PixPatHandle pp,const RGBColor *myColor);
void          DisposePixPat(PixPatHandle pp);

Getting Pattern Resources

PatHandle  GetPattern(short patternID);
void       GetIndPattern(Pattern *thePat,short patternListID,short index);

Changing the Pen and BackGround Pixel Pattern and Bit Pattern

void  BackPixPat(PixPatHandle pp);
void  PenPixPat(PixPatHandle pp);
void  BackPat(const Pattern *pat);
void  PenPat(const Pattern *pat);

Drawing Lines

void  MoveTo(short h,short v);
void  Move(short dh,short dv);
void  LineTo(short h,short v);
void  Line(short dh,short dv);

Drawing Rectangles

void  FrameRect(const Rect *r);
void  PaintRect(const Rect *r);
void  FillRect(const Rect *r,ConstPatternParam pat);
void  FillCRect(const Rect *r,PixPatHandle pp);
void  InvertRect(const Rect *r);
void  EraseRect(const Rect *r);

Drawing Rounded Rectangles

void  FrameRoundRect(const Rect *r,short ovalWidth,short ovalHeight);
void  PaintRoundRect(const Rect *r,short ovalWidth,short ovalHeight);
void  FillRoundRect(const Rect *r,short ovalWidth,short ovalHeight,const Pattern *pat;
void  FillCRoundRect(const Rect *r,short ovalWidth,short ovalHeight,PixPatHandle pp);
void  InvertRoundRect(const Rect *r,short ovalWidth,short ovalHeight);
void  EraseRoundRect(const Rect *r,short ovalWidth,short ovalHeight);

Drawing Ovals

void  FrameOval(const Rect *r);
void  PaintOval(const Rect *r);
void  FillOval(const Rect *r,const Pattern *pat);
void  FillCOval(const Rect *r,PixPatHandle pp);
void  InvertOval(const Rect *r);
void  EraseOval(const Rect *r);

Drawing Arcs and Wedges

void  FrameArc(const Rect *r,short startAngle,short arcAngle);
void  PaintArc(const Rect *r,short startAngle,short arcAngle);
void  FillArc(const Rect *r,short startAngle,short arcAngle,const Pattern *pat);
void  FillCArc(const Rect *r,short startAngle,short arcAngle,PixPatHandle pp);
void  InvertArc(const Rect *r,short startAngle,short arcAngle);
void  EraseArc(const Rect *r,short startAngle,short arcAngle);

Drawing and Painting Polygons

void  FramePoly(PolyHandle poly);
void  PaintPoly(PolyHandle poly);
void  FillPoly(PolyHandle poly,const Pattern *pat);
void  FillCPoly(PolyHandle poly,PixPatHandle pp);
void  InvertPoly(PolyHandle poly);
void  ErasePoly(PolyHandle poly);

Drawing Regions

void  FrameRgn(RgnHandle rgn);
void  PaintRgn(RgnHandle rgn);
void  FillCRgn(RgnHandle rgn,PixPatHandle pp);
void  EraseRgn(RgnHandle rgn);
void  InvertRgn(RgnHandle rgn);
void  FillRgn(RgnHandle rgn, const Pattern *pat);

Setting Text Characteristics

void  TextFont(short font);
void  TextFace(short face);
void  TextMode(short mode);
void  TextSize(short size);
void  SpaceExtra(Fixed extra);
void  GetFontInfo(FontInfo *info);

Drawing and Measuring Text

void   DrawChar(short ch);
void   DrawString(ConstStr255Param s);
void   DrawText(const void *textBuf,short firstByte,short byteCount);
short  CharWidth(short ch);
short  StringWidth(ConstStr255Param s);

Copying Images

void  CopyBits(const BitMap *srcBits,const BitMap *dstBits,const Rect *srcRect,
      const Rect *dstRect,short mode,RgnHandle maskRgn);
void  CopyMask(const BitMap *srcBits,const BitMap *maskBits,const BitMap *dstBits,
      const Rect *srcRect,const Rect *maskRect,const Rect *dstRect);
void  CopyDeepMask(const BitMap *srcBits,const BitMap *maskBits,const BitMap *dstBits,
      const Rect *srcRect,const Rect *maskRect,const Rect *dstRect,short mode, 
      RgnHandle maskRgn)

Getting and Setting the Highlight Colour and HighLight Mode

void   HiliteColor(const RGBColor *color);
void   LMGetHiliteRGB(RGBColor *hiliteRGBValue);
void   LMSetHiliteRGB(const RGBColor *hiliteRGBValue);
UInt8  LMGetHiliteMode(void);
void   LMSetHiliteMode(UInt8 value);

Creating and Disposing of Colour Tables

CTabHandle  GetCTable(short ctID);
void        DisposeCTable(CTabHandle cTable);

Creating and Managing Polygons

PolyHandle  OpenPoly(void);
void        ClosePoly(void);
void        KillPoly(PolyHandle poly);
void        OffsetPoly(PolyHandle poly,short dh,short dv);

Creating and Managing Rectangles

void     SetRect(Rect *r,short left,short top,short right,short bottom);
void     OffsetRect(Rect *r,short dh,short dv);
void     InsetRect(Rect *r,short dh,short dv);
Boolean  SectRect(const Rect *src1,const Rect *src2,Rect *dstRect);
void     UnionRect(const Rect *src1,const Rect *src2,Rect *dstRect);
Boolean  PtInRect(Point pt,const Rect *r);
void     Pt2Rect(Point pt1,Point pt2,Rect *dstRect);
void     PtToAngle(const Rect *r,Point pt,short *angle);
Boolean  EqualRect(const Rect *rect1,const Rect *rect2);
Boolean  EmptyRect(const Rect *r);

Creating and Managing Regions

RgnHandle  NewRgn(void);
void       OpenRgn(void);
void       CloseRgn(RgnHandle dstRgn);
void       DisposeRgn(RgnHandle rgn);
void       CopyRgn(RgnHandle srcRgn,RgnHandle dstRgn);
void       SetEmptyRgn(RgnHandle rgn);
void       SetRectRgn(RgnHandle rgn,short left,short top,short right,short bottom);
void       RectRgn(RgnHandle rgn,const Rect *r);
void       OffsetRgn(RgnHandle rgn,short dh,short dv);
void       InsetRgn(RgnHandle rgn,short dh,short dv);
void       SectRgn(RgnHandle srcRgnA,RgnHandle srcRgnB,RgnHandle dstRgn);
void       UnionRgn(RgnHandle srcRgnA,RgnHandle srcRgnB,RgnHandle dstRgn);
void       DiffRgn(RgnHandle srcRgnA,RgnHandle srcRgnB,RgnHandle dstRgn);
void       XorRgn(RgnHandle srcRgnA,RgnHandle srcRgnB,RgnHandle dstRgn);
Boolean    PtInRgn(Point pt,RgnHandle rgn);
Boolean    RectInRgn(const Rect *r,RgnHandle rgn);
Boolean    EqualRgn(RgnHandle rgnA,RgnHandle rgnB);
Boolean    EmptyRgn(RgnHandle rgn);
OSErr      BitMapToRegion(RgnHandle region,const BitMap *bMap);

Scaling and Mapping Points, Rectangles, Polygons, and Regions

void  ScalePt(Point *pt,const Rect *srcRect,const Rect *dstRect);
void  MapPt(Point *pt,const Rect *srcRect,const Rect *dstRect);
void  MapRect(Rect *r,const Rect *srcRect,const Rect *dstRect);
void  MapRgn(RgnHandle rgn,const Rect *srcRect,const Rect *dstRect);
void  MapPoly(PolyHandle poly,const Rect *srcRect,const Rect *dstRect);

Determining Whether QuickDraw has Finished Drawing

Boolean  QDDone(GrafPtr port);

Retrieving Color QuickDraw Result Codes

short  QDError(void);

Managing Port Rectangles and Clipping Regions

void  ScrollRect(const Rect *r,short dh,short dv,RgnHandle updateRgn);
void  SetOrigin(short h,short v);
void  PortSize(short width,short height);
void  MovePortTo(short leftGlobal,short topGlobal);
void  GetClip(RgnHandle rgn);
void  SetClip(RgnHandle rgn);
void  ClipRect(const Rect *r);

Manipulating Points in Colour Graphics Ports

void     GlobalToLocal(Point *pt);
void     LocalToGlobal(Point *pt);
void     AddPt(Point src,Point *dst);
void     SubPt(Point *src,Point *dst);
void     SetPt(Point *pt,short h,short v);
Boolean  EqualPt(Point pt1,Point pt2);
Boolean  GetPixel(short h,short v);

Relevant Appearance Manager Data Types and Functions

The following data types and functions are available only in Mac OS 8.5 (Appearance Manager 1.1) or later.

Data Types

typedef struct OpaqueThemeDrawingState *ThemeDrawingState;

Functions

OSStatus  NormalizeThemeDrawingState(void);
OSStatus  GetThemeDrawingState(ThemeDrawingState *outState);
OSStatus  SetThemeDrawingState(ThemeDrawingState inState,Boolean inDisposeNow);
OSStatus  DisposeThemeDrawingState(ThemeDrawingState inState);

Go to Demo

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »
MoreFun Studios has announced Season 4,...
Tension has escalated in the ever-volatile world of Arena Breakout, as your old pal Randall Fisher and bosses Fred and Perrero continue to lob insults and explosives at each other, bringing us to a new phase of warfare. Season 4, Into The Fog of... | Read more »
Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links below... | Read more »
Marvel Future Fight celebrates nine year...
Announced alongside an advertising image I can only assume was aimed squarely at myself with the prominent Deadpool and Odin featured on it, Netmarble has revealed their celebrations for the 9th anniversary of Marvel Future Fight. The Countdown... | Read more »
HoYoFair 2024 prepares to showcase over...
To say Genshin Impact took the world by storm when it was released would be an understatement. However, I think the most surprising part of the launch was just how much further it went than gaming. There have been concerts, art shows, massive... | Read more »
Explore some of BBCs' most iconic s...
Despite your personal opinion on the BBC at a managerial level, it is undeniable that it has overseen some fantastic British shows in the past, and now thanks to a partnership with Roblox, players will be able to interact with some of these... | Read more »
Play Together teams up with Sanrio to br...
I was quite surprised to learn that the massive social network game Play Together had never collaborated with the globally popular Sanrio IP, it seems like the perfect team. Well, this glaring omission has now been rectified, as that instantly... | Read more »

Price Scanner via MacPrices.net

B&H has 13-inch M2 MacBook Airs with 16GB...
B&H Photo has 13″ MacBook Airs with M2 CPUs, 16GB of memory, and 256GB of storage in stock and on sale for $1099, $100 off Apple’s MSRP for this configuration. Free 1-2 day delivery is available... Read more
14-inch M3 MacBook Pro with 16GB of RAM avail...
Apple has the 14″ M3 MacBook Pro with 16GB of RAM and 1TB of storage, Certified Refurbished, available for $300 off MSRP. Each MacBook Pro features a new outer case, shipping is free, and an Apple 1-... Read more
Apple M2 Mac minis on sale for up to $150 off...
Amazon has Apple’s M2-powered Mac minis in stock and on sale for $100-$150 off MSRP, each including free delivery: – Mac mini M2/256GB SSD: $499, save $100 – Mac mini M2/512GB SSD: $699, save $100 –... Read more
Amazon is offering a $200 discount on 14-inch...
Amazon has 14-inch M3 MacBook Pros in stock and on sale for $200 off MSRP. Shipping is free. Note that Amazon’s stock tends to come and go: – 14″ M3 MacBook Pro (8GB RAM/512GB SSD): $1399.99, $200... Read more
Sunday Sale: 13-inch M3 MacBook Air for $999,...
Several Apple retailers have the new 13″ MacBook Air with an M3 CPU in stock and on sale today for only $999 in Midnight. These are the lowest prices currently available for new 13″ M3 MacBook Airs... Read more
Multiple Apple retailers are offering 13-inch...
Several Apple retailers have 13″ MacBook Airs with M2 CPUs in stock and on sale this weekend starting at only $849 in Space Gray, Silver, Starlight, and Midnight colors. These are the lowest prices... Read more
Roundup of Verizon’s April Apple iPhone Promo...
Verizon is offering a number of iPhone deals for the month of April. Switch, and open a new of service, and you can qualify for a free iPhone 15 or heavy monthly discounts on other models: – 128GB... Read more
B&H has 16-inch MacBook Pros on sale for...
Apple 16″ MacBook Pros with M3 Pro and M3 Max CPUs are in stock and on sale today for $200-$300 off MSRP at B&H Photo. Their prices are among the lowest currently available for these models. B... Read more
Updated Mac Desktop Price Trackers
Our Apple award-winning Mac desktop price trackers are the best place to look for the lowest prices and latest sales on all the latest computers. Scan our price trackers for the latest information on... Read more
9th-generation iPads on sale for $80 off MSRP...
Best Buy has Apple’s 9th generation 10.2″ WiFi iPads on sale for $80 off MSRP on their online store for a limited time. Prices start at only $249. Sale prices for online orders only, in-store prices... Read more

Jobs Board

*Apple* Systems Administrator - JAMF - Activ...
…**Public Trust/Other Required:** None **Job Family:** Systems Administration **Skills:** Apple Platforms,Computer Servers,Jamf Pro **Experience:** 3 + years of Read more
Liquor Stock Clerk - S. *Apple* St. - Idaho...
Liquor Stock Clerk - S. Apple St. Boise Posting Begin Date: 2023/10/10 Posting End Date: 2024/10/14 Category: Retail Sub Category: Customer Service Work Type: Part Read more
Top Secret *Apple* System Admin - Insight G...
Job Description Day to Day: * Configure and maintain the client's Apple Device Management (ADM) solution. The current solution is JAMF supporting 250-500 end points, Read more
Sonographer - *Apple* Hill Imaging Center -...
Sonographer - Apple Hill Imaging Center - Evenings Location: York Hospital, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now Read more
Beauty Consultant - *Apple* Blossom Mall -...
Beauty Consultant - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.