home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
x
/
xibm.zip
/
apa16
/
apa16Text.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-19
|
17KB
|
702 lines
/***********************************************************
Copyright 1991 by the Massachusetts Institute of Technology
All rights reserved.
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 the Massachusetts
Institute of Technology (M.I.T.) not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
#ifndef lint
static char *rcsid = "$Id: apa16Text.c,v 5.4 1992/03/20 01:01:14 jfc Exp $";
#endif
#include "X.h"
#include "Xmd.h"
#include "Xproto.h"
#include "misc.h"
#include "dixfontstr.h"
#include "gcstruct.h"
#include "scrnintstr.h"
#include "regionstr.h"
#include "pixmapstr.h"
#include "mfb.h"
#include "ibmTrace.h"
#include "OScompiler.h"
#include "apa16Decls.h"
#include "apa16Hdwr.h"
#include "apa16Font.h"
#include "apa16Text.h"
#ifndef NO_FUNCTION_PROTOTYPES
static void apa16UncachedImageText8(DrawablePtr, GCPtr, int, int, int, char *, FontEncoding);
static int apa16UncachedPolyText8();
static void apa16FastCopyChars(apa16FontPtr, int, int, int, char *, int);
static void apa16CopyCharsClip1(apa16FontPtr, int, int, int, char *, int, BoxPtr);
static void apa16CopyCharsClipN(apa16FontPtr, int, int, int, char *, int, RegionPtr);
#else
static void apa16UncachedImageText8();
static int apa16UncachedPolyText8();
static void apa16FastCopyChars(), apa16CopyCharsClip1(), apa16CopyCharsClipN();
#endif
void
apa16ImageText8(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
FontPtr pFont;
apa16FontPtr aFont;
RegionPtr pRegion;
int w;
int i;
if ((pGC->planemask & 1) == 0 || count == 0)
return;
pFont = pGC->font;
aFont = (apa16FontPtr)FontGetPrivate(pFont,apa16FontPrivateIndex);
if (aFont == 0 || pDrawable->type != DRAWABLE_WINDOW ||
! APA16_FONT_CACHED(aFont))
{
apa16UncachedImageText8(pDrawable, pGC, x, y, count, chars, Linear8Bit);
return;
}
TRACE(("apa16ImageText8(%x,%x,%d,%d,%d,%x) %x\n",
pDrawable,pGC,x,y,count,chars,chars[0]));
x += pDrawable->x;
y += pDrawable->y;
pRegion = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
w = 0;
if (aFont->afWidth > 0)
w += count * aFont->afWidth;
else
for (i = 0; i < count; i++)
w += aFont->afChars->chars[chars[i]]->metrics.characterWidth;
/* If it were known that the area drawn did not extend beyond the bounding
box of the font, this statement could be conditional on
if (pGC->fgPixel == 0 || pGC->bgPixel == 1)
*/
{
register unsigned short cmd;
int descent = pFont->info.fontDescent;
int ascent = pFont->info.fontAscent;
BoxRec box;
BoxPtr pbox;
int n;
if (pGC->bgPixel)
{
APA16_GET_CMD_FILL(RROP_WHITE, cmd);
}
else
{
APA16_GET_CMD_FILL(RROP_BLACK, cmd);
}
/* Clear an area starting at (x,y - ascent),
with width = (sum of char overall widths)
and height = ascent + descent */
box.x1 = x;
box.x2 = x + w;
box.y1 = y - ascent;
box.y2 = y + descent;
/* The apa16 code only uses the mi region code, so it is not
necessary to call via the function pointer in the screen
structure. */
switch (miRectIn(pRegion, &box))
{
case rgnIN:
FILL_RECT(cmd, box.x2, box.y2, w, ascent + descent);
break;
case rgnOUT:
break;
case rgnPART:
n = REGION_NUM_RECTS(pRegion);
pbox = REGION_RECTS(pRegion);
while(n-- > 0)
{
int x1 = MAX(x, pbox->x1);
int y1 = MAX(y - ascent, pbox->y1);
int x2 = MIN(x + w, pbox->x2);
int y2 = MIN(y + descent, pbox->y2);
if (x2 > x1 && y2 > y1)
{ FILL_RECT(cmd, x2, y2, x2 - x1, y2 - y1); }
pbox++;
}
break;
}
/* This is actually incorrect: it should print whatever parts of
the characters extend beyond the bounding box. */
if (pGC->fgPixel == pGC->bgPixel)
return;
}
{
register unsigned short cmd;
register int i;
int descent, ascent;
BoxRec box;
char c;
/* Verify that all the characters are cached. */
i = count;
for(i = 0; i < count; i++)
if (!APA16_CHAR8_CACHED(aFont,chars[i]))
break;
if (i != count && !apa16CacheChars(aFont, (unsigned char *)chars, count))
goto fail;
APA16_TOUCH_FONT(aFont, 0);
if (pGC->fgPixel)
{
APA16_GET_CMD_COPY(ROP_RECT_COPY, GXor, cmd);
}
else
{
APA16_GET_CMD_COPY(ROP_RECT_COPY, GXandInverted, cmd);
}
/* Assume that no character extends further to the left of the
origin than the first character and that no other character
draws to the right of the right edge of the last character.
It is possible to design a font where this assumption is false. */
c = chars[0];
if (aFont->afChars->chars[c] == 0)
c = aFont->afDefChar;
/* Image text definition requires the window to be cleared to the
font ascent and descent, but this test must check the max bounds
because some characters could extend outside the region. */
descent = FONTMAXBOUNDS(pFont,descent);
ascent = FONTMAXBOUNDS(pFont,ascent);
box.x1 = x + aFont->afChars->chars[c]->metrics.leftSideBearing;
box.y1 = y - ascent;
box.y2 = y + descent;
c = chars[count - 1];
if (aFont->afChars->chars[c] == 0)
c = aFont->afDefChar;
box.x2 = x + w - aFont->afChars->chars[c]->metrics.characterWidth
+ aFont->afChars->chars[c]->metrics.rightSideBearing;
/* If no clipping needs to be done, use the fast routine. */
if (miRectIn(pRegion, &box) == rgnIN)
{
apa16FastCopyChars(aFont, x, box.y2, cmd, chars, count);
return;
}
if(REGION_NUM_RECTS(pRegion) == 1)
apa16CopyCharsClip1(aFont, x, y, cmd, chars, count, REGION_RECTS(pRegion));
else
apa16CopyCharsClipN(aFont, x, y, cmd, chars, count, pRegion);
return;
}
fail:
apa16UncachedImageText8(pDrawable, pGC, x-pDrawable->x, y-pDrawable->y,
count, chars, Linear8Bit);
return;
}
int
apa16PolyText8(pDrawable, pGC, xOrig, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int xOrig, y;
int count;
char *chars;
{
int x;
FontPtr pFont;
apa16FontPtr aFont;
RegionPtr pRegion;
if (count == 0)
return xOrig;
pFont = pGC->font;
aFont = (apa16FontPtr)FontGetPrivate(pFont,apa16FontPrivateIndex);
if (aFont == 0 || pDrawable->type != DRAWABLE_WINDOW
|| (pGC->planemask & 1) == 0
|| APA16_FONT_CACHED(aFont) == 0)
{
return apa16UncachedPolyText8(pDrawable, pGC, xOrig, y, count, chars, Linear8Bit);
}
TRACE(("apa16PolyText8(%x,%x,%d,%d,%d,%x) %x\n",
pDrawable,pGC,xOrig,y,count,chars,chars[0]));
x = xOrig + pDrawable->x;
y += pDrawable->y;
pRegion = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
{
register unsigned short cmd;
register int i;
int descent, ascent;
int w;
BoxRec box;
char c;
/* Verify that all the characters are cached. This could be made
smarter, by copying the cached characters and only drawing the
uncached characters using the slow method. */
i = count;
for(i = 0; i < count; i++)
if (!APA16_CHAR8_CACHED(aFont,chars[i]))
break;
if (i != count && !apa16CacheChars(aFont, (unsigned char *)chars, count))
return apa16UncachedPolyText8(pDrawable, pGC, xOrig,
y - pDrawable->y, count, chars, Linear8Bit);
APA16_TOUCH_FONT(aFont, 0);
w = 0;
if (aFont->afWidth > 0)
w += count * aFont->afWidth;
else
for(i = 0; i < count; i++)
{
CharInfoPtr cip = aFont->afChars->chars[chars[i]];
if (cip)
w += cip->metrics.characterWidth;
else
w += aFont->afDefWidth;
}
switch(((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop)
{
case RROP_WHITE:
APA16_GET_CMD_COPY(ROP_RECT_COPY, GXor, cmd);
break;
case RROP_BLACK:
APA16_GET_CMD_COPY(ROP_RECT_COPY, GXandInverted, cmd);
break;
case RROP_INVERT:
APA16_GET_CMD_COPY(ROP_RECT_COPY, GXxor, cmd);
break;
case RROP_NOP:
default: /* for compiler data flow analysis */
return xOrig + w;
}
c = chars[0];
if (aFont->afChars->chars[c] == 0)
c = aFont->afDefChar;
descent = FONTMAXBOUNDS(pFont,descent);
ascent = FONTMAXBOUNDS(pFont,ascent);
box.x1 = x - aFont->afChars->chars[c]->metrics.leftSideBearing;
box.y1 = y - ascent;
box.y2 = y + descent;
c = chars[count - 1];
if (aFont->afChars->chars[c] == 0)
c = aFont->afDefChar;
box.x2 = x + w - aFont->afChars->chars[c]->metrics.characterWidth
+ aFont->afChars->chars[c]->metrics.rightSideBearing;
if (miRectIn(pRegion, &box) == rgnIN)
apa16FastCopyChars(aFont, x, box.y2, cmd, chars, count);
else if(REGION_NUM_RECTS(pRegion) == 1)
apa16CopyCharsClip1(aFont, x, y, cmd, chars, count, REGION_RECTS(pRegion));
else
apa16CopyCharsClipN(aFont, x, y, cmd, chars, count, pRegion);
return xOrig + w;
}
}
/* Code stolen from mipolytext.c */
void
apa16ImageText16(pDraw, pGC, x, y, count, chars)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
CharInfoPtr *charinfo;
unsigned long n;
FontPtr font = pGC->font;
TRACE(("apa16ImageText16(%x,%x,%d,%d,%d,%x) %x,%x\n", pDraw, pGC, x, y, count, chars, chars[0], chars[1]));
if(!(charinfo = (CharInfoPtr *)ALLOCATE_LOCAL(count*sizeof(CharInfoPtr))))
return;
GetGlyphs(font, (unsigned long)count, (unsigned char *)chars,
(FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
&n, charinfo);
if (n != 0)
{
QUEUE_WAIT();
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n,
charinfo, FONTGLYPHS(font));
}
DEALLOCATE_LOCAL(charinfo);
}
static int
apa16UncachedPolyText8(pDraw, pGC, x, y, count, chars)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
register CharInfoPtr *charinfo;
unsigned long n, i;
int w;
TRACE(("apa16PolyText8(%x,%x,%d,%d,%d,%x) %x (uncached)\n", pDraw, pGC, x, y, count, chars, chars[0]));
if(!(charinfo = (CharInfoPtr *)ALLOCATE_LOCAL(count*sizeof(CharInfoPtr ))))
return x;
GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars,
Linear8Bit, &n, charinfo);
w = 0;
for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
if (n != 0)
{
QUEUE_WAIT();
(*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, n,
charinfo, FONTGLYPHS(pGC->font));
}
DEALLOCATE_LOCAL(charinfo);
return x+w;
}
int
apa16PolyText16(pDraw, pGC, x, y, count, chars)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
unsigned short *chars;
{
register CharInfoPtr *charinfo;
unsigned long n, i;
int w;
if(!(charinfo = (CharInfoPtr *)ALLOCATE_LOCAL(count*sizeof(CharInfoPtr))))
return x;
GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars,
(FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
&n, charinfo);
TRACE(("apa16PolyText16(%x,%x,%d,%d,%d,%x) %x,%x\n", pDraw, pGC, x, y, count, chars, chars[0], chars[1]));
w = 0;
for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
if (n != 0)
{
QUEUE_WAIT();
(*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, n,
charinfo, FONTGLYPHS(pGC->font));
}
DEALLOCATE_LOCAL(charinfo);
return x+w;
}
static void
apa16UncachedImageText8(DrawablePtr pDraw, GCPtr pGC, int x, int y,
int count, char *chars, FontEncoding fontEncoding)
{
register CharInfoPtr *charinfo;
unsigned long n;
FontPtr font = pGC->font;
if(!(charinfo = (CharInfoPtr *)ALLOCATE_LOCAL(count*sizeof(CharInfoPtr))))
return;
GetGlyphs(font, (unsigned long)count, (unsigned char *)chars,
fontEncoding, &n, charinfo);
TRACE(("apa16UncachedImageText8\n"));
if (n != 0)
{
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n,
charinfo, FONTGLYPHS(font));
}
DEALLOCATE_LOCAL(charinfo);
return;
}
/* This is called when all chars are unclipped. It avoids reloading
the dest y coordinate register for each character, so drawing is
about 25% faster. */
static void
apa16FastCopyChars(font,x,y,cmd,chars,count)
apa16FontPtr font;
int x,y;
int cmd;
char *chars;
int count;
{
register apa16FCCharInfo *fcip = font->afChars;
int descent = FONTMAXBOUNDS(font->afFont,descent);
/* COPY_RECT_SETY reserves space for count commands and loads the
text y register */
COPY_RECT_SETY(count,y);
cmd |= EXEC_MASK;
while(count-- > 0)
{
register CharInfoPtr cip;
char c = *chars++;
int x2, h, w;
cip = fcip->chars[c];
if (cip == 0)
{
c = font->afDefChar;
cip = fcip->chars[c];
}
x2 = x + cip->metrics.rightSideBearing;
h = cip->metrics.ascent + descent;
if (h > 0 && (w = GLYPHWIDTHPIXELS(cip)) > 0)
{
COPY_RECT_CONT(cmd, x2, APA16_CHAR8_CACHE_X(fcip, c),
APA16_CHAR8_CACHE_Y(fcip, c), w, h);
}
x += cip->metrics.characterWidth;
}
return;
}
/* Draw characters, clipping with a single rectangle.
When possible, this function also avoids reloading the y register. */
static void
apa16CopyCharsClip1(font, x, y, cmd, chars, count, pbox)
apa16FontPtr font;
int x,y;
int cmd;
char *chars;
int count;
BoxPtr pbox;
{
register apa16FCCharInfo *fcip = font->afChars;
char def = font->afDefChar;
int descent = FONTMAXBOUNDS(font->afFont,descent);
short lasty;
RESERVE_QUEUE(7 * count);
apa16Qoffset--;
REG_LOAD(10,y+descent,1);
lasty = y + descent;
cmd |= EXEC_MASK;
while (count-- > 0)
{
int x1, y1, x2, y2, xc, yc;
char c = *chars++;
register CharInfoPtr cip = fcip->chars[c];
if (cip == 0)
{
c = def;
cip = fcip->chars[c];
}
x1 = x + cip->metrics.leftSideBearing;
if (x1 < pbox->x1)
{
x1 = pbox->x1;
}
xc = APA16_CHAR8_CACHE_X(fcip, c);
x2 = x + cip->metrics.rightSideBearing;
if (x2 > pbox->x2)
{
xc += (pbox->x2 - x2);
x2 = pbox->x2;
}
if (x2 <= x1)
{
x += cip->metrics.characterWidth;
continue;
}
y1 = y - cip->metrics.ascent;
if (y1 < pbox->y1)
{
y1 = pbox->y1;
}
yc = APA16_CHAR8_CACHE_Y(fcip, c);
y2 = y + descent;
if (y2 > pbox->y2)
{
yc += (pbox->y2 - y2);
y2 = pbox->y2;
}
if (y2 > y1)
{
if (y2 != lasty)
{
apa16Qoffset--;
REG_LOAD(10,y2,1);
lasty = y2;
}
COPY_RECT_CONT(cmd, x2, xc, yc, x2 - x1, y2 - y1);
}
x += cip->metrics.characterWidth;
}
return;
}
static void
apa16CopyCharsClipN(font, x, y, cmd, chars, count, pRegion)
apa16FontPtr font;
int x,y;
int cmd;
char *chars;
int count;
RegionPtr pRegion;
{
int descent = FONTMAXBOUNDS(font->afFont,descent);
int nbox = REGION_NUM_RECTS(pRegion);
BoxPtr pbox = REGION_RECTS(pRegion);
apa16FCCharInfo *fcip = font->afChars;
while(count-- > 0)
{
BoxRec box;
char c = *chars++;
if (fcip->chars[c] == 0)
c = font->afDefChar;
box.x1 = x+fcip->chars[c]->metrics.leftSideBearing;
box.x2 = x+fcip->chars[c]->metrics.rightSideBearing;
box.y1 = y-fcip->chars[c]->metrics.ascent;
box.y2 = y+descent;
if (box.x1 >= box.x2 || box.y1 >= box.y2)
{
x += fcip->chars[c]->metrics.characterWidth;
continue;
}
switch(miRectIn(pRegion, &box))
{
case rgnIN:
COPY_RECT(cmd, box.x2, box.y2,
APA16_CHAR8_CACHE_X(fcip, c),
APA16_CHAR8_CACHE_Y(fcip, c),
box.x2 - box.x1, box.y2 - box.y1);
break;
case rgnOUT:
break;
case rgnPART:
{
BoxPtr pboxtmp = pbox;
int nboxtmp = nbox;
while (nboxtmp-- > 0)
{
int x1, x2, y1, y2, xc, yc;
x1 = box.x1;
if (x1 < pboxtmp->x1)
{
x1 = pboxtmp->x1;
}
xc = APA16_CHAR8_CACHE_X(fcip, c);
x2 = box.x2;
if (x2 > pboxtmp->x2)
{
xc += (pboxtmp->x2 - x2);
x2 = pboxtmp->x2;
}
if (x2 <= x1)
{
pboxtmp++;
continue;
}
y1 = box.y1;
if (y1 < pboxtmp->y1)
{
y1 = pboxtmp->y1;
}
yc = APA16_CHAR8_CACHE_Y(fcip, c);
y2 = box.y2;
if (y2 > pboxtmp->y2)
{
yc += (pboxtmp->y2 - y2);
y2 = pboxtmp->y2;
}
if (y2 > y1)
{
COPY_RECT(cmd, x2, y2, xc, yc, x2 - x1, y2 - y1);
}
pboxtmp++;
} /* end while nboxtmp */
}
} /* end switch */
x += fcip->chars[c]->metrics.characterWidth;
} /* end while count */
return;
}