[Date Prev][Date Next][Thread Prev][Thread Next][Author Index][Date Index][Thread Index]

Re: Multiple font editor



>From acad!acaduk!crystal!dave Wed Sep  6 09:11:52 1989

	I've now been given some time to work on Xanadu-related stuff and am planning,
	as a first stage to rewrite the editor I did in C++, adding support for
	multiple windows, multiple fonts, etc.

	However I believe you were planning to work on something similar and it's
	a bit of waste to duplicate someone else's work.

	Have you started working on this ? (if so could you send me source for what
	you've done ?)

Right:  I'm close to having compositors, and display stuff working.
This is the stuff that decides where to put things on the screen.  I'm
currently focusing on getting this to display properly, then I'll make
selection work.  The code uses update messages between various data models to
handle changes.  The code I'v egot was written in smalltalk and automatically
translated to c++, I'm doing most of the work in smalltalk.  

The design is as follows

XuBE <-> DataModel <-> AbstractModel <-> DisplayModel -> Image ->Screen

The DataModel extends the Waldo interface to documents and links
and does the interpretation of link ends into abstractStyle stuff
which is the stuff that the
AbstractModel deals with.  The AbstractModel deals with an address space
that contains emements from many Xu documents, for example  an abstractModel
could have 40 characters from doucment A than a quotation form document B of 
93 characters, then more from doc A.  The AbstractModel address 40 would 
correspond to character 40 in doc A, while 41 would correspond to char 1 
in doc B.  The abstract Model takes care of those mappings.  The Abstract
model knows about  style information of the form "english language text"
& "Chicago styple paragraph, type 2a" i.e. abstract characterizations.

Thes are turned into concrete stuff in the DisplayModel, where the types are
exemplified by "macfont currier 8 bold" and the like and alphabet-types
are resolved into bitlength-appropriate stuff or bytes (one common case).
Our code has char * strings only as a kludge, they will all goaway,except
as low level implementation interfaces to windowsystems, in those special
cases where they are in fact the correct thing.

DisplayModel contains compositors that allow the mapping of stuff onto
the screen, and positions on the screen back to the selected stuff
in the Displaymodel's addressspace (very similar or identical to the 
AbstractModel's addressspace).

Image & Screen are memory & actual display, respectively, and are intended
to be very system specific.

Much of the above code is written, certainly the compositors are.  
The DataModel stuff is being written by Hugh Hoover heh@xanadu, it should
be ready soon.  The rest I'm at the stage of getting to display in 
sun's OpenView X/NeWS window system, the selection mechanism will have
to be redone.  Currently I'm focusing on getting characters on the screen.

I expect most of this code will be portable between systems, certainly 
down through the Displaymodel the only things that are system dependent
are pointer types for some of the lowlevel windowsystem stuff.
 
Let me know when you want to see this, I wouldn't suggest that
anyone else try to use it till Hugh & I get it working. The code style
may take some getting used to as it is pure object style code, so you
might want to look at it early.  I was very surprised in switching to
smalltalk.  I took some c++ and translated it into smalltalk, then had it 
automatically translated back, in many cases I got the same code back!
In some cases the indentation and spacing were exact!  This is a far cry
from previous experience with automatically translated code.

I`m including a file of c++ code  and it's hxx include file as an example:

I expect some questions to be generated by this message, so lets hear them!

XLineComp.hxx

/* Copyright Xanadu Operating Company.  All Rights Reserved.
	6 September 1989 at 12:35:41 am
	From Objectworks for Smalltalk-80, Version 2.5 beta of 28 May 1989 */

#ifndef XLINECOMP_HXX
#define XLINECOMP_HXX

class XLineComp;
#include "Xpp.hxx"
#include "Iterator.hxx"
/* generic hxx header. */
/* Include the .hxx file for the superclass. */
#include "XMondoCompositor.hxx"

CLASS (XLineComp,XMondoCompositor) {
PUBLIC:
public: /* accessing */
	virtual IntegerVar height ();
	
	virtual IntegerVar nextStart ();
	
	virtual IntegerVar width ();
	
public: /* composing */
	virtual CompositorEnum compose (DisplayModel * model, IntegerVar posIn, Layout * layout);
	
	/* This computes the maximum ascent and descent from the newly composed 
	runs. This could be done during composition, but it clutters the method. The 
	composition method should at least keep a flag noting whether all the runs 
	have the same ascent and descent. */
	virtual void computeHeights ();
	
public: /* displaying */
	virtual void displayOnAt (DisplayModel * model, Image * aMedium, Point * displayPos);
	
protected:
	IntegerVar lineWidth;
	IntegerVar lineAscent;
	IntegerVar lineDescent;
	IntegerVar runStop;
};

/* methods defined in Smalltalk class. */
/* instance creation */
#endif /* XLINECOMP_HXX */


/* Copyright Xanadu Operating Company.  All Rights Reserved.
	6 September 1989 at 12:35:39 am
	From Objectworks for Smalltalk-80, Version 2.5 beta of 28 May 1989 */

#include "XLineComp.hxx"
#include "XLineComp-pvt.hxx"
#include "XRunComp.hxx"

DEFINE_CLASS (XLineComp,XMondoCompositor);

/* accessing */
IntegerVar XLineComp::height () {
	return lineAscent + lineDescent;
}

IntegerVar XLineComp::nextStart () {
	return runStop;
}

IntegerVar XLineComp::width () {
	return lineWidth;
}

/* composing */
CompositorEnum XLineComp::compose (DisplayModel * model, IntegerVar posIn, Layout * layout) {
	IntegerVar modelPos;
	XRunComp * runSub;
	CompositorEnum stopF;
	CompositorEnum subFlag;
	Iterator OF1(XRunComp) * compSubs;
	IntegerVar curWidth;
	
	runStop = modelPos = posIn;
	lineWidth = curWidth = 0;
	subs = compSubs = iterator();
	stopF = none;
	while (stopF == none && !model->pastEnd(modelPos)) {
		runSub = NEW(XRunComp());
		subFlag = runSub->compose(model, modelPos, layout, curWidth);
		compSubs = compSubs->with(NEW(XSub(runSub, NEW(Point(curWidth, runSub->deltaY())), modelPos)));
		if (runSub->hasSeparator()) {
			subs = compSubs;
			lineWidth = curWidth + runSub->widthToSeparator();
			runStop = runSub->nextAfterSeparator();
		}
		modelPos = runSub->nextStart();
		curWidth = curWidth + runSub->runWidth();
		if (!(subFlag == endOfRun)) {
			stopF = subFlag;
		}
	}
	if (stopF == lineOverflow) {
		/* Back up to the last linebreak. */
		if (runSub->hasSeparator()) {
			runSub->commitSeparator();
		} else {
			CAST(XRunComp,subs->reverse()->iterand())->commitSeparator();
		}
	} else {
		subs = compSubs;
		lineWidth = curWidth;
		runStop = modelPos;
	}
	this->computeHeights();
	return model->pastEnd(modelPos) ? endOfParagraph : endOfLine;
}

void XLineComp::computeHeights () {
	/* This computes the maximum ascent and descent from the newly composed 
	runs. This could be done during composition, but it clutters the method. The 
	composition method should at least keep a flag noting whether all the runs 
	have the same ascent and descent. */
	
	lineAscent = lineDescent = 0;
	for (Iterator * LoopCurIt = subs; LoopCurIt->notEmpty(); LoopCurIt = LoopCurIt->withoutIt()) {
		XSub * sub = CAST(XSub,LoopCurIt->iterand());
		XRunComp * run;
		
		run = CAST(XRunComp,sub->compositor());
		if (run->ascent() > lineAscent) {
			lineAscent = run->ascent();
		}
		if (run->descent() > lineDescent) {
			lineDescent = run->descent();
		}
	}
}

/* displaying */
void XLineComp::displayOnAt (DisplayModel * model, Image * aMedium, Point * displayPos) {
	for (Iterator * LoopCurIt = subs; LoopCurIt->notEmpty(); LoopCurIt = LoopCurIt->withoutIt()) {
		XSub * sub = CAST(XSub,LoopCurIt->iterand());
		sub->compositor()->displayOnAt(model, aMedium, displayPos->plus(sub->displayPos()));
	}
}


/* methods defined in Smalltalk class. */
/* instance creation */