|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 22245 (0x56e5)
Types: TextFile
Names: »text.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z«
└─⟦2109abc41⟧
└─⟦this⟧ »./X.V10R4/libibm/libsrc/text.c«
#ifndef lint
static char *rcsid_text_c = "$Header: text.c,v 10.1 86/11/19 10:44:22 jg Exp $";
#endif lint
/* Copyright 1985 Massachusetts Institute of Technology */
/* text.c - X text based functions
*
* PrintText Prints text with source font
* PrintTextMask Prints text with mask font
* CopyText Copy text to bitmap
* TextWidth Returns width of a piece of text in a font
* CharWidth Returns width of a character in a font
* OffScreenText Utility rtn to optimize text blts using
* an offscreen buffer
* CopyScreenBits Utility rtn used to grab a rectangular area
* of the screen and place it in an offscreen buffer.
*
* Authors:
* Dan Stone & Scott Bates
* Brown University
* IRIS, Box 1946
* Providence, RI 02912
*
*
* Copyright (c) 1986 Brown University
*
* Permission to use, copy, modify and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies, and that both
* that copyright notice and this permission notice appear in supporting
* documentation, and that the name of Brown University not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. Brown University makes no
* representations about the suitability of this software for any purpose.
* It is provided "as-is" without express or implied warranty.
*/
#include "private.h"
#include "bitblt.h"
#include "text.h"
/*
* Print text with font as source
*/
PrintText (string, strlen, font, fore, back, charpad, spacepad, dstx, dsty,
clips, clipcount, func, zmask)
register char *string;
FONT *font;
register strlen, dstx;
register charpad, spacepad;
int fore, back, dsty;
CLIP *clips;
int clipcount, zmask;
int func;
{
FontPriv *fpriv = FDATA(font);
BITMAP *cbm = fpriv->chrs;
register c;
register charwidth;
register buf_wd, buf_ht;
register nchar;
register srcOx;
int srcCx;
#ifdef TRACE_X
fprintf(stderr, "In PrintText\n");
fflush(stderr);
#endif TRACE_X
/*
* Limit text to one plane
*/
if ((zmask & 1) == 0)
return;
/*
* Change combination rule to reflect specified
* foreground and background colors
*/
if (fore & 1)
func += 0x20;
if (back & 1)
func += 0x10;
func = FBMap[func];
/*
* While we have more than CH_THRESHOLD characters then we will put
* the text into an offscreen buffer then blow it up onto the screen.
* When it drops below this threshold then it is no longer efficient
* to go to an offscreen buffer and we will go directly to the screen
* with bitblt.
*/
if (fpriv->offscr != NILBITMAP) {
while (strlen > CH_THRESHOLD) {
/*
* Make sure that CopyScreenBits() stays on the screen.
* Note: We are assuming the destination bitmap and the
* screen bitmap are already zero based and we
* are assuming that the txtbm is at least the
* width of the screen.
*/
if ((buf_ht = font->height) > (pbm.height - dsty)) {
buf_ht = pbm.height - dsty;
}
if ((buf_wd = ((fpriv->maxwidth + charpad + spacepad) *
strlen)) > (pbm.width - dstx)) {
if ((buf_wd = pbm.width - dstx) > txtbm.width) {
buf_wd = txtbm.width;
}
}
/*
* Make sure the sizes are non-zero.
*/
if (buf_ht < 1 || buf_wd < 1) {
break;
}
/*
* Bring area on the screen into the offscreen buffer.
*/
CopyScreenBits(dstx, dsty, buf_wd, buf_ht, &txtbm);
/*
* Blt as much text as one can into the offscreen
* buffer. NOTE: Because CopyScreenBits rounds over
* to a long word (4 bytes) boundary we must move
* the text over in the offscreen area by modulo 32.
* Also note that offscreen_text returns the source
* corner in srcCx.
*/
srcOx = dstx & 0x1F;
if ((nchar = OffScreenText(&txtbm,font,string,strlen,
charpad,spacepad,srcOx,
&srcCx,func)) < 1) {
/*
* Check nchar before going on and get out of
* the loop if its less than 1.
*/
break;
}
/*
* Move the string up and the char count down.
*/
string += nchar;
strlen -= nchar;
/*
* Put the offscreen buffer back onto the screen using
* CopyBits().
*
* Make source and destination rectangles.
*/
FillInRect(srcOx,0,srcCx - srcOx,buf_ht,&SrcRect);
FillInRect(dstx,dsty,(srcCx - srcOx),
buf_ht,&DstRect);
/*
* Put the offscreen text buffer back onto the screen.
*/
CopyBits((u_short *)txtbm.data,txtbm.width,txtbm.height,
&SrcRect, (u_short *) pbm.data, pbm.width,
pbm.height, &DstRect, NILMASK, NIL, NIL,
GXcopy, clipcount, clips);
/*
* Adjust destination address (dstx)
*/
dstx = DstRect.corner_x + charpad;
}
}
/*
* Now loop thru the string until we are finished.....
*/
while (--strlen >= 0) {
/*
* Character we are working on
*/
c = (int) (*string++);
/*
* Check for legal character.
*/
if (c < font->first || c > font->last)
continue;
/*
* Get width of current character
*/
if((charwidth = fpriv->widths[c]) > 0) {
/*
* Make source and destination rectangles
*/
FillInRect(0,font->height * (c - font->first),
charwidth, font->height, &SrcRect);
FillInRect(dstx, dsty, charwidth, font->height,
&DstRect);
/*
* Blt character to frame buffer
*/
CopyBits((u_short *) cbm->data, cbm->width, cbm->height,
&SrcRect, (u_short *) pbm.data, pbm.width,
pbm.height, &DstRect, NILMASK, NIL, NIL, func,
clipcount, clips);
/*
* Adjust destination address (dstx)
*/
dstx += charwidth + charpad;
}
/*
* Adjust destination address by size of space character
*/
if (c == font->space)
dstx += spacepad;
}
}
/*
* Print text with font as mask
*/
PrintTextMask (string, strlen, font, srcpix, charpad, spacepad, dstx, dsty,
clips, clipcount, func, zmask)
register char *string;
FONT *font;
register strlen, charpad, spacepad, dstx;
int srcpix, dsty;
CLIP *clips;
int clipcount, zmask;
int func;
{
register FontPriv *fpriv = FDATA(font);
int charsize = BitmapSize(fpriv->maxwidth, font->height);
u_short *charmask;
register charwidth;
register c;
register srcOx;
register nchar;
int srcCx;
#ifdef TRACE_X
fprintf (stderr, "In PrintTextMask\n");
fflush (stderr);
#endif TRACE_X
/*
* Limit text to one plane
*/
if ((zmask & 1) == 0)
return;
/*
* While we have more than CH_THRESHOLD characters then we will put
* the text into an offscreen buffer then blow it up onto the screen.
* When it drops below this threshold then it is no longer efficient
* to go to an offscreen buffer and we will go directly to the screen
* with bitblt.
*/
if (fpriv->offscr != NILBITMAP) {
while (strlen > CH_THRESHOLD) {
/*
* Clear the offscreen buffer area.
*/
bzero((char *)txtbm.data,
(font->height * ((txtbm.width + 15)/16)) << 1);
/*
* Blt as much text as one can into the offscreen
* buffer. Note that offscreen_text returns the source
* corner in srcCx.
*/
srcOx = dstx & 0xF;
if ((nchar = OffScreenText(&txtbm,font,string,strlen,
charpad,spacepad,srcOx,
&srcCx,GXcopy)) < 1) {
/*
* Check nchar before going on and get out of
* the loop if its less than 1.
*/
break;
}
/*
* Move the string up and the char count down.
*/
string += nchar;
strlen -= nchar;
/*
* Put the offscreen buffer back onto the screen using
* CopyBits().
*
* Make source and destination rectangles.
*/
FillInRect((dstx - srcOx),dsty,srcCx,
font->height,&DstRect);
/*
* Using the offscreen bitmap as a mask, copy
* the text to the screen.
*/
CopyBits((u_short *) ConstantTiles[srcpix & 1],
NIL, NIL, NILRECT,
(u_short *) pbm.data, pbm.width, pbm.height,
&DstRect, (u_short *)txtbm.data, txtbm.width,
font->height, MAKE_TILE_RULE(func), clipcount,
clips);
/*
* Adjust destination address (dstx)
*/
dstx = DstRect.corner_x + charwidth + charpad;
}
}
/*
* Now loop thru the string until we are finished.....
*/
while (--strlen >= 0) {
/*
* Character we are working on
*/
c = (int) (*string++);
/*
* Check for legal character.
*/
if (c < font->first || c > font->last)
continue;
/*
* Get width of current character
*/
if((charwidth = fpriv->widths[c]) > 0) {
/*
* Use character as clipping mask
*/
charmask = (u_short *) ((long) fpriv->chrs->data +
charsize * (c - font->first));
/*
* Fill in destination rectangle
*/
FillInRect(dstx, dsty, charwidth, font->height,
&DstRect);
/*
* Blt character to frame buffer using font
* character as mask
*/
CopyBits((u_short *) ConstantTiles[srcpix & 1], NIL,
NIL, NILRECT, (u_short *) pbm.data, pbm.width,
pbm.height, &DstRect,
charmask, charwidth, font->height,
MAKE_TILE_RULE(func), clipcount, clips);
/*
* Adjust destination address (dstx) by character
* pad amount
*/
dstx += charwidth + charpad;
}
/*
* Adjust destination address by size of space character
*/
if (c == font->space)
dstx += spacepad;
}
}
/*
* Copy text to bitmap
*/
CopyText (string, strlen, font, bm)
register char *string;
register strlen;
FONT *font;
BITMAP *bm;
{
register FontPriv *fpriv = FDATA(font);
BITMAP *cbm = fpriv->chrs;
register c;
register charwidth;
register dstx = 0;
#ifdef TRACE_X
fprintf(stderr, "In CopyText\n");
fflush(stderr);
#endif TRACE_X
/*
* loop thru string until we are finished.....
*/
while (--strlen >= 0) {
/*
* Character we are working on
*/
c = (int) (*string++);
/*
* Check for legal character.
*/
if (c < font->first || c > font->last)
continue;
/*
* Get width of current character
*/
if((charwidth = fpriv->widths[c]) == 0)
continue;
/*
* Fill in source and destination rectangles
*/
FillInRect(0,font->height * (c - font->first),
charwidth, font->height, &SrcRect);
FillInRect(dstx, 0, charwidth, font->height, &DstRect);
/*
* Blt character to bitmap
*/
CopyBits((u_short *)cbm->data,cbm->width, cbm->height, &SrcRect,
(u_short *) bm->data, bm->width, bm->height, &DstRect,
NILMASK, NIL, NIL, GXcopy, 0, NILCLIP);
/*
* Adjust destination address (dstx)
*/
dstx += charwidth;
}
}
/*
* Compute width of a piece of text in a font
*/
int TextWidth (string, strlen, spacepad, font)
register char *string;
register int strlen;
int spacepad;
register FONT *font;
{
register u_int c;
register short *widths;
register int width = 0;
#ifdef TRACE_X
fprintf(stderr, "In TextWidth\n");
fflush(stderr);
#endif TRACE_X
if (font->fixed) {
/*
* Font is fixed width
*/
/*
* Compute total width of text string
*/
width = strlen * font->avg_width;
if (spacepad) {
/*
* Add spacepad amount to the total width for each
* space character found in text string
*/
while (--strlen >= 0) {
if (*string++ == font->space)
width += spacepad;
}
}
} else {
/*
* Font is variable width
*/
/*
* get pointer to width table
*/
widths = FDATA(font)->widths;
/*
* Loop thru text string
*/
while (--strlen >= 0) {
/*
* Get current character
*/
c = *string++;
if (c >= font->first && c <= font->last) {
/*
* Valid character
*/
if (c == font->space) {
/*
* Character is a space so add
* spacepad amount to total width
*/
width += spacepad;
}
/*
* Find width of this character in width
* table and add it to total
*/
width += widths[c];
}
}
}
return (width);
}
/*
* Determine width of a character in a font
*/
int CharWidth(c, font)
register u_int c;
register FONT *font;
{
#ifdef TRACE_X
fprintf(stderr, "In CharWidth\n");
fflush(stderr);
#endif TRACE_X
if (c < font->first || c > font->last)
/*
* Character not in font
*/
return (0);
else if (font->fixed)
/*
* Font is a fixed width so return the
* average character width for the font
*/
return (font->avg_width);
else
/*
* Font is variable width so determine
* width of character from font width table
*/
return (FDATA(font)->widths[c]);
}
/*
* OffScreenText puts text from "font" into "buf_bm". It assumes the font
* bitmap * has its characters "left justified". It returns the rightmost
* X position in "cornerX".
*/
static
OffScreenText(buf_bm,font,string,ch_count,ch_pad,sp_pad,dstX,cornerX,func)
BITMAP *buf_bm; /* Offscreen buffer bitmap */
FONT *font; /* Font structure */
char *string; /* String of characters to be put up. */
int ch_count; /* Number of characters in the string */
int ch_pad; /* Space between characters */
int sp_pad; /* Amount of space a pad character is. */
int dstX; /* The spot in the offscreen buffer where
the text is to start. */
int *cornerX; /* Send the rightmost X position back to the
caller for use with the bltter. */
int func; /* Function (or combination rule) to be used
with text */
{
register u_char *dst;
register u_char *src;
register u_long src_nextline, dst_nextline;
register int height;
register u_short leftmask, rtmask;
int c, shift, ndst_shorts, inv_shift, i, start_dst;
int dst_nextcol, src_nextcol, nsrc_shorts, ht_plus1;
short chrs_nshorts, buf_nshorts;
u_long bitptr;
long maxbitptr;
int shorts_per_char;
u_char *chrs_data;
FontPriv *fpriv = FDATA(font);
short *char_widths = fpriv->widths;
#ifdef TRACE_X
fprintf (stderr, "In OffScreenText\n");
fflush (stderr);
#endif TRACE_X
/*
* Calculate, in shorts, the width of both the chrs and
* buffer bitmaps.
*/
chrs_nshorts = BTOW(fpriv->maxwidth);
maxbitptr = fpriv->offscr->width;
buf_nshorts = BTOW(maxbitptr);
/*
* Set up to go through the string of characters.
*/
bitptr = dstX;
src_nextline = MUL_2(chrs_nshorts);
dst_nextline = MUL_2(buf_nshorts);
/*
* Setup for text blt
*/
ht_plus1 = font->height + 1;
shorts_per_char = MUL_2(chrs_nshorts * font->height);
chrs_data = (u_char *)fpriv->chrs->data;
/*
* Blt text string into offscreen buffer
*/
switch (func) {
case (GXclear):
CopyText_LOOP(GXclear_MASK, GXclear_OP);
break;
case (GXand):
CopyText_LOOP(GXand_MASK, GXand_OP);
break;
case (GXandReverse):
CopyText_LOOP(GXandReverse_MASK, GXandReverse_OP);
break;
case (GXcopy):
CopyText_LOOP(GXcopy_MASK, GXcopy_OP);
break;
case (GXandInverted):
CopyText_LOOP(GXandInverted_MASK, GXandInverted_OP);
break;
case (GXnoop):
break;
case (GXxor):
CopyText_LOOP(GXxor_MASK, GXxor_OP);
break;
case (GXor):
CopyText_LOOP(GXor_MASK, GXor_OP);
break;
case (GXnor):
CopyText_LOOP(GXnor_MASK, GXnor_OP);
break;
case (GXequiv):
CopyText_LOOP(GXequiv_MASK, GXequiv_OP);
break;
case (GXinvert):
CopyText_LOOP(GXinvert_MASK, GXinvert_OP);
break;
case (GXorReverse):
CopyText_LOOP(GXorReverse_MASK, GXorReverse_OP);
break;
case (GXcopyInverted):
CopyText_LOOP(GXcopyInverted_MASK, GXcopyInverted_OP);
break;
case (GXorInverted):
CopyText_LOOP(GXorInverted_MASK, GXorInverted_OP);
break;
case (GXnand):
CopyText_LOOP(GXnand_MASK, GXnand_OP);
break;
case (GXset):
CopyText_LOOP(GXset_MASK, GXset_OP);
break;
}
/*
* Remove the last charcter pad added to the last character.
*/
bitptr -= ch_pad;
/*
* Return right most X value and character count to caller
*/
if (bitptr > dstX)
*cornerX = bitptr;
else
*cornerX = dstX;
return(ch_count);
}
#if (APA8 || APA8C)
#define DSTBITS ((u_short *)DstBits)
#define SRCBITS ((u_short *)SrcBits)
#define SIZE_OF_SHORT (sizeof(u_short))
#define SIZE_OF_APA8_SHORT (sizeof(u_short) * 2)
/*
* Copy shorts off of the screen (pbm) into the destination bitmap.
*/
static
CopyScreenBits(StartX, StartY, Width, Height, DstBitmap)
int StartX, StartY;
int Width;
register Height;
BITMAP *DstBitmap;
{
register nwords;
register char *DstBits;
register DstRowBytes;
register SrcRowBytes;
register char *SrcBits;
#ifdef TRACE_X
fprintf (stderr, "In CopyScreenBits\n");
fflush (stderr);
#endif TRACE_X
/*
* Check StartX and StartY and offset the destination pointer if
* one or both are negative and change the source pointer.
*/
if (StartX < 0) {
/*
* Make sure there are words to be taken off the screen.
*/
if ((nwords = BTOW(StartX + Width)) < 1) {
return;
}
DstRowBytes = MUL_2(DIV_BPW(DstBitmap->width) - nwords);
SrcRowBytes = MUL_4(DIV_BPW(pbm.width));
DstBits = (char *)DstBitmap->data + MUL_2(DIV_BPW(-StartX));
if (StartY < 0) {
/*
* Figure out the number of scanlines to be copied.
*/
if ((Height += StartY) < 1) {
return;
}
DstBits += (-StartY * (DstBitmap->width >> 3));
SrcBits = (char *)pbm.data;
} else {
SrcBits = (char *)pbm.data + (StartY * SrcRowBytes);
}
} else {
/*
* Make sure there are words to be taken off the screen.
*/
if ((nwords = BTOW(StartX + Width) - DIV_BPW(StartX)) < 1) {
return;
}
DstRowBytes = MUL_2(DIV_BPW(DstBitmap->width) - nwords);
SrcRowBytes = MUL_4(DIV_BPW(pbm.width));
DstBits = (char *)DstBitmap->data;
if (StartY < 0) {
/*
* Figure out the number of scanlines to be copied.
*/
if ((Height += StartY) < 1) {
return;
}
DstBits += (-StartY * (DstBitmap->width >> 3));
SrcBits = (char *)pbm.data + MUL_4(DIV_BPW(StartX));
} else {
SrcBits = (char *)pbm.data + (StartY * SrcRowBytes) +
MUL_4(BTOW(StartX));
}
}
if (nwords > 1) { /* more than one short wide */
int tmpnWords = nwords;
SrcRowBytes -= MUL_4(nwords);
while(1) {
do {
*DSTBITS = *SRCBITS;
DstBits += SIZE_OF_SHORT;
SrcBits += SIZE_OF_APA8_SHORT;
} while(--nwords > 0);
if(--Height) {
DstBits += DstRowBytes;
SrcBits += SrcRowBytes;
nwords = tmpnWords;
} else {
break;
}
}
} else { /* one short wide */
/*
* Should not have subtracted (nwords << 2) from
* DstRowBytes. So now that we know nwords == 1 we will
* add (nwords << 2) == 4 back to DstRowBytes.
*/
DstRowBytes += 4;
while(1) {
*DSTBITS = *SRCBITS;
if(--Height) {
DstBits += DstRowBytes;
SrcBits += SrcRowBytes;
} else {
break;
}
}
}
}
#else
#define DSTBITS ((u_long *)DstBits)
#define SRCBITS ((u_long *)SrcBits)
#define SIZE_OF_LONG sizeof(u_long)
/*
* Copy long words off of the screen (pbm) into the destination bitmap.
*/
static
CopyScreenBits(StartX, StartY, Width, Height, DstBitmap)
int StartX, StartY;
int Width;
register Height;
BITMAP *DstBitmap;
{
register nwords;
register char *DstBits;
register DstRowBytes;
register SrcRowBytes;
register char *SrcBits;
#if (APA16 && USE_APA16_HDWR)
int tmp;
#endif (APA16 && USE_APA16_HDWR)
#ifdef TRACE_X
fprintf (stderr, "In CopyScreenBits\n");
fflush (stderr);
#endif TRACE_X
/*
* Check StartX and StartY and offset the destination pointer if
* one or both are negative and change the source pointer.
*/
if (StartX < 0) {
/*
* Make sure there are words to be taken off the screen.
*/
if ((nwords = BTOL(StartX + Width)) < 1) {
return;
}
/*
* DstRowBytes and SrcRowBytes are MUL_4'ed so that
* they are the number of BYTES the address must be incremented.
*/
DstRowBytes = MUL_4(DIV_BPL(DstBitmap->width) - nwords);
SrcRowBytes = MUL_4(DIV_BPL(pbm.width));
DstBits = (char *)DstBitmap->data + MUL_4(DIV_BPL(-StartX));
if (StartY < 0) {
/*
* Figure out the number of scanlines to be copied.
*/
if ((Height += StartY) < 1) {
return;
}
DstBits += (-StartY * (DstBitmap->width >> 3));
SrcBits = (char *)pbm.data;
} else {
SrcBits = (char *)pbm.data + (StartY*SrcRowBytes);
}
} else {
/*
* Make sure there are words to be taken off the screen.
*/
if ((nwords = BTOL(StartX + Width) - DIV_BPL(StartX)) < 1) {
return;
}
DstRowBytes = MUL_4(DIV_BPL(DstBitmap->width) - nwords);
SrcRowBytes = MUL_4(DIV_BPL(pbm.width));
DstBits = (char *)DstBitmap->data;
if (StartY < 0) {
/*
* Figure out the number of scanlines to be copied.
*/
if ((Height += StartY) < 1) {
return;
}
DstBits += (-StartY * (DstBitmap->width >> 3));
SrcBits = (char *)pbm.data + MUL_4(DIV_BPL(StartX));
} else {
SrcBits = (char *)pbm.data + (StartY * SrcRowBytes) +
MUL_4(DIV_BPL(StartX));
}
}
#if (APA16 && USE_APA16_HDWR)
#include "../bitblt/bitblt_apa16.h"
/*
* If we are using the APA-16 hardware then we must wait for the
* hardware to be done with the screen.
*/
WAIT_QUE(tmp, 0);
#endif (APA16 && USE_APA16_HDWR)
if (nwords > 1) { /* more than one long wide */
int tmpnWords = nwords;
SrcRowBytes -= MUL_4(nwords);
while(1) {
do {
*DSTBITS = *SRCBITS;
DstBits += SIZE_OF_LONG;
SrcBits += SIZE_OF_LONG;
} while(--nwords > 0);
if(--Height) {
DstBits += DstRowBytes;
SrcBits += SrcRowBytes;
nwords = tmpnWords;
} else {
break;
}
}
} else { /* one long wide */
/*
* Should not have subtracted MUL_4(nwords) from
* DstRowBytes. So now that we know nwords == 1 we will
* add MUL_4(nwords) == 4 back to DstRowBytes.
*/
DstRowBytes += 4;
while(1) {
*DSTBITS = *SRCBITS;
if(--Height) {
DstBits += DstRowBytes;
SrcBits += SrcRowBytes;
} else {
break;
}
}
}
}
#endif (APA8 || APA8C)