Miscellaneous Notes About Release 13
Here are some random thoughts and handy words about
MacApp & ACS Release 13. They are not presented in any
particular order.
Contents
- fprintf
- char* Coercion
- Returning CViewRect, CStr255_AC
- No More Square Dots
- No More Non-Styled Text
- No More Segments
- z-Ordered Clipping
- Control Removal
- View Coordinate System
fprintf
All fprintfs have been changed to ProgramReport_AC or
ProgramBreak_AC.
char* Coercion
MacApp no longer uses the char* coercion operator.
However we have left it in place so that developers are free
to use it if they wish:
#if defined(qBackwardCompatible) && qBackwardCompatible
// Returns a copy of the string on the stack.
// (as a null terminated c style string)
// Note that this will not work when inlining
// is turned off. MacApp makes no use of this
// operator internally. However, it is still
// provided as a convenience for compatibility.
// Ideally you should write code that constructs
// a CChar255_AC in place from your string
inline operator const char*() const
{ return CChar255_AC(*this); }
#endif
Returning CViewRect, CStr255_AC
Many functions now return a CViewRect, CViewPoint or
CStr255_AC instead of passing the result through a
parameter. This change avoids making assumptions about the
passed-in value, optimizes parameter assignment and copying,
reduces code size, and is much more convenient in usage.
Many people do not realize that C/C++ compilers handle
structure (class) function results by passing a hidden
pointer to the resulting structure to the called function.
Thus:
SetFrame(GetFrame(), kInvalidate);
is equivalent to
VRect theFrame;
GetFrame(theFrame);
SetFrame(theFrame, kInvalidate);
in terms of the actual code generated, with the exception
that smart compilers can be even more aggressive in their
optimization because the named object for the VRect is now
anonymous. Named objects cannot be as aggressively
optimized, that's why it is often better to construct
objects only where needed such as:
SetFrame(VRect(10,10,100, 100), kInvalidate);
Also, C/V/Rect/Point and CStrxxx have efficient inline
initializers that guarantee the objects are in usable shape
which is generally a good thing, however, having functions
like GetFrame() return the VRect means that the intermediate
value can use a value constructor rather than a default
constructor, followed by assignment or some other means of
storing of value.
Thus, the first example above actually generates
less and faster code while being more
convenient in usage. Note that this is true for the
functions that now return CStrxxx's as well.
No More Square Dots
Square dots was only used for old imagewriter code that
made undocumented usage of the print record. When we cleaned
MacApp up to only use approved, documented interfaces use of
undocumented information had to be removed. By the way,
there is no other printer that uses non-square dots, and the
imagewriter is capable of square dots, thus a continuing
source of code headaches and maintenance was removed.
No More Non-Styled Text
The isStyledText setting for TTEView has been removed,
along with non-styled text support. Non-styled TextEdit is
quite unfriendly to internationalization. MacApp makes
extensive use of Script manager calls that are only friendly
with styled TextEdit.
No More Segments
We no longer support segmentation for 68K builds in
MacApp. In fact, all #pragma segment directives
have been removed from the source code.
Maintaining segmentation is a nightmare. ACS has never
had any segmentation pragmas and the ones in MacApp were
seriously outdated. We did some sensitivity analysis on
building 68K applications single segment and found that the
overall memory requirements were not significantly different
in most cases and actually lower in some cases. Further, we
realized a performance benefit.
Developer feedback to the suggestion of going
single-segment was predominantly positive.
z-Ordered Clipping
z-order clipping is now automatic. You may not even
notice it because it is so fast.
R13 views have the following characteristics:
- Arbitrary region shaping that is as FAST as old
fashioned rectangular views but much much cooler because
views can be shaped like your favorite cartoon character
and will only draw, hililte, update, click test, etc.
within the arbitrary region.
- z-order clipping of overlapping sibling views. Yes,
those "Tick" shaped views can overlap each other and will
in fact clip each other in z-order.
- But wait, there's more! There is also z-order
clipping of subviews. Thus if you have a view that has an
opaque subview (more on that in a minute) that subview
will be clipped out of the focus for the parent view.
This results in significantly less flicker when drawing
things like a gray backdrop with big white scrollers
since the area of the scrollers will be clipped when
drawing the gray backdrop.
All this clipping is fast and automatic, but is also
easily controllable via several avenues. First, there is a
new member function for TViews called
IsOpaque() . This method is used to indicate
when a view is considered 'opaque', that is, it draws it's
entire contents and no other bits are visible through it.
Only opaque views are clipped. A view is considered opaque
if its fIsOpaque flag is set or if it has an
adorner that returns true for the adorner's
IsOpaque . Erase adorners are considered opaque,
they pass true for the default
isOpaque parameter to the TAdorner constructor.
TScrollers, TScrollBars are also considered opaque, they
call SetOpacity(true) at construction.
IsOpaque is non-virtual. To be opaque,
adorners or views must set their fIsOpaque flag
via SetOpacity() .
Control Removal
We now only remove controls from the WindowRecord's
control list during activation and de-activation, the rest
of the time we leave the controls alone. This allows system
level utilities that expect to find controls on the
WindowRecord's control list to still do so. Notably, this
lets Speech Recognition and Apple Guide locate buttons and
operate them. Also, we leave the control's location in
window coordinates (where they are expected to be found by
aforesaid utilities) except during actual MacApp drawing or
operation of the control. During that time we move the
control into MacApp space, do the operation, and then
restore the control.
View Coordinate System
The following words were written recently and I thought
you all might appreciate reading them:
fLocation is the location of a view
expressed in its superview's coordinate system.
fTranslation is the offset to the
zero point of the view's coordinate system. Views can have
non-zero based coordinate systems by calling SetTranslation.
Scrollers override this method in order to preserve screen
bits when changing the origin.
fViewToQDOffset is the difference
between the current view's origin in "View" space (which is
32bits in size) and its origin in QuickDraw space (which is
only 16 bits in size). This lets us think and calculate in
"View coordinates" but only convert them to QuickDraw
coordinates at the last possible moment (via ViewToQD) when
making QuickDraw calls. In fact, since most of the time you
are not making QD calls, this means that MacApp stays in
"View" coordinates most of the time.
fQDOrigin is the actual origin that
will be set in QuickDraw when the view is focused. This
origin is moved as necessary to accomodate scrolling and
such but it is also calculated in (TView::UpdateCoordinates)
in conjunction with fViewToQDOffset such that the fQDOrigin
is always a multiple of 1024. The reason we do this is to
overcome a problem with QD (that is in fact a shortcoming of
most other frameworks and view system!!) When you move the
QD origin in order to have a non-zero origin for a view (for
scrolling and such) you can't just set the origin anywhere
you (darn well) please. No, no, no, no, no! If you do that
then the lines, shapes, regions and other stuff you draw
with QD will work just fine... but, patterns will not render
correctly since they are always drawn relative to QD's
origin. Thus, we always move the QD origin in a power of two
that is large enough to probably keep from interfering with
large patterns. There is a discussion of the issue in
comments in the UpdateCoordinates method.
|