Utility isBaseGlyph(X) returns YES if the character X is a normal spacing mark.

Utility isKnownNSM(X) returns YES if the character X is a simple non-spacing mark such as acute, umlaut, cedilla, dot-below, etc.

Utility isDetachedMark(X) returns YES if the character X is a non-spacing mark that is detached, such as an acute or umlaut. Otherwise, if the mark is attached (e.g., cedilla) it returns NO.

Utility isAboveMark(X) returns YES if the character X is a non-spacing mark that is above the base, such as an umlaut. Otherwise if the mark is a below-mark, it returns NO.

Utility DisplayGlyph(G, x, y) displays the glyph G at point x,y.

Utility widthOfGlyph(G) returns the advance width of the glyph (not the bounding rect).

Utility boundingRectOfGlyph(G) returns the bounding rectangle for a glyph.

Function RenderBaseAndDiacriticalMarks(GlyphStream) {
    CapHeight = ...; /* Set this to the cap height of the font */
    Xpos = 0; Ypos = 0; /* Set to the base of the current "line" */
    DisplayedBaseGlyph = NO;
    
    while ( more glyphs are in the stream ) {
	BaseGlyph = GlyphStream[index].theGlyph;
	BaseRect = boundingRectOfGlyph(BaseGlyph);
	if (isBaseGlyph(GlyphStream[index].repChar)) {
	    DisplayGlyph(BaseGlyph, Xpos, Ypos);
	    ++index;
	    DisplayedBaseGlyph = YES;
	    if ( no more glyphs in the stream ) break;
	} 
	if (isKnownNSM(GlyphStream[index].repChar)) {
	    if (! DisplayedBaseGlyph) {
		/*
		 * Special processing for lines beginning with NSMs without bases?
		 */
		BaseRect = ...;
	    }
	    while (isKnownNSM(GlyphStream[index].repChar)) {
		CurrentGlyph = GlyphStream[index].theGlyph;
		MarkRect = boundingRectOfGlyph(CurrentGlyph);
		TheGap = (isDetachedMark(CurrentGlyph) ? (CapHeight / 8.0) : 0.0);
		/*
		* Calculate where to put the mark relative to the base coordinates.
		*/
		Xpoint = (BaseRect.x - MarkRect.x) + ((BaseRect.w - MarkRect.w) / 2.0);
		if (isAboveMark(CurrentGlyph)) {
		    Ypoint = ((BaseRect.y + BaseRect.h) + TheGap) - MarkRect.y;
		} else {
		    Ypoint = BaseRect.y - MarkRect.y - MarkRect.h - TheGap;
		}
		/*
		 * Display the non-spacing glyph relative to the base point.
		 */
		rx = RelativeMoveTo(Xpos, Xpoint); ry = RelativeMoveTo(Ypos, Ypoint);
		DisplayGlyph(CurrentGlyph, rx, ry);
		/*
		 * Calculate the new, enclosing bounding rect for the combination,
		 * and draw a box around the whole thing.
		 * Xextent, Yextent is the upper right corner of the mark glyph...
		 */ 
		Xextent = Xpoint + MarkRect.x + MarkRect.w;
		Yextent = Ypoint + MarkRect.y + MarkRect.h;
		NewBaseBRect.x = min(BaseRect.x, Xpoint + MarkRect.x);
		NewBaseBRect.y = min(BaseRect.y, Ypoint + MarkRect.y);
		NewBaseBRect.w = max(BaseRect.x + BaseRect.w, Xextent) - BaseRect.x;
		NewBaseBRect.h = max(BaseRect.y + BaseRect.h, Yextent) - BaseRect.y;
		/*
		 * Reset the "bounding rect" to the total enclosing rect calculated above...
		 */
		BaseRect = NewBaseBRect;
    		++index;
	    }
	} else if (! isBaseGlyph(GlyphStream[index].theGlyph) {
	    /*
	     * if we get here, we have encountered an unknown mark or don't know how to
	     * render it. Time to punt and do "something reasonable" to display it.
	     */
	    ++index;
	}
	/*
	 * Move the display point forward by the character width. The width might be
	 * modified by the various NSMs, or affected by kerning.
	 */
	Xpos += widthOfGlyph(BaseGlyph);
    }
}


======================================================================================================

FontBBox -168 -218 1000 898
CapHeight 662

C 69 ; WX 611 ; N E ; B 12 0 597 662 ;
C 81 ; WX 722 ; N Q ; B 34 -178 701 676 ;
C 199 ; WX 333 ; N dotaccent ; B 118 523 216 623 ;
C 200 ; WX 333 ; N dieresis ; B 18 523 315 623 ;
C 202 ; WX 333 ; N ring ; B 67 512 266 711 ;
C 203 ; WX 333 ; N cedilla ; B 52 -215 261 0 ;

% Times-Roman bounding rects (x, y, w, h):
% E rect = (12, 0, 585, 662)
% Q rect = (34, -178, 667, 854)
% X rect = (10, 0, 694, 662)
% Diaeresis rect = (18, 523, 297, 100)
% Ring rect = (67, 512, 259, 100)