593 lines
15 KiB
C
593 lines
15 KiB
C
|
|
/********************************************************************
|
|
|
|
In this file we have GC level replacements for PolyText8/16,
|
|
ImageText8/16, ImageGlyphBlt and PolyGlyphBlt for NonTE (proportional)
|
|
fonts. The idea is that everything in this file is device independent.
|
|
The mentioned GCOps are merely wrappers for the
|
|
PolyGlyphBltNonTEColorExpansion and ImageGlyphBltNonTEColorExpansion
|
|
functions which calculate the boxes containing arbitrarily clipped
|
|
text and passes them to the NonTEGlyphRenderer which will usually
|
|
be a lower level XAA function which renders these clipped glyphs using
|
|
the basic color expansion functions exported by the chipset driver.
|
|
The NonTEGlyphRenderer itself may optionally be driver supplied to
|
|
facilitate work-arounds/optimizations at a higher level than usual.
|
|
|
|
Written by Mark Vojkovich (mvojkovi@ucsd.edu)
|
|
|
|
********************************************************************/
|
|
|
|
#ifdef HAVE_XORG_CONFIG_H
|
|
#include <xorg-config.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include "misc.h"
|
|
#include "xf86.h"
|
|
#include "xf86_OSproc.h"
|
|
|
|
#include <X11/X.h>
|
|
#include <X11/fonts/font.h>
|
|
#include "scrnintstr.h"
|
|
#include "dixfontstr.h"
|
|
#include "xf86str.h"
|
|
#include "xaa.h"
|
|
#include "xaacexp.h"
|
|
#include "xaalocal.h"
|
|
#include "gcstruct.h"
|
|
#include "pixmapstr.h"
|
|
|
|
|
|
static void ImageGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn,
|
|
int xInit, int yInit, FontPtr font,
|
|
int fg, int bg, unsigned planemask,
|
|
RegionPtr cclip, int nglyph,
|
|
unsigned char* gBase, CharInfoPtr *ppci);
|
|
static int PolyGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn,
|
|
int xInit, int yInit, FontPtr font,
|
|
int fg, int rop, unsigned planemask,
|
|
RegionPtr cclip, int nglyph,
|
|
unsigned char* gBase, CharInfoPtr *ppci);
|
|
|
|
/********************************************************************
|
|
|
|
GC level replacements for PolyText8/16 and ImageText8/16
|
|
for NonTE fonts when using color expansion.
|
|
|
|
********************************************************************/
|
|
|
|
|
|
int
|
|
XAAPolyText8NonTEColorExpansion(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
char *chars )
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
unsigned long n;
|
|
int width = 0;
|
|
|
|
(*pGC->font->get_glyphs)(pGC->font, (unsigned long)count,
|
|
(unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo);
|
|
|
|
if(n) {
|
|
width = PolyGlyphBltNonTEColorExpansion( infoRec->pScrn,
|
|
x + pDraw->x, y + pDraw->y, pGC->font,
|
|
pGC->fgPixel, pGC->alu, pGC->planemask,
|
|
pGC->pCompositeClip, n, FONTGLYPHS(pGC->font),
|
|
infoRec->CharInfo);
|
|
}
|
|
|
|
return (x + width);
|
|
}
|
|
|
|
|
|
int
|
|
XAAPolyText16NonTEColorExpansion(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
unsigned short *chars )
|
|
{
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
unsigned long n;
|
|
int width = 0;
|
|
|
|
(*pGC->font->get_glyphs)(
|
|
pGC->font, (unsigned long)count, (unsigned char *)chars,
|
|
(FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
|
|
&n, infoRec->CharInfo);
|
|
|
|
if(n) {
|
|
width = PolyGlyphBltNonTEColorExpansion( infoRec->pScrn,
|
|
x + pDraw->x, y + pDraw->y, pGC->font,
|
|
pGC->fgPixel, pGC->alu, pGC->planemask,
|
|
pGC->pCompositeClip, n, FONTGLYPHS(pGC->font),
|
|
infoRec->CharInfo);
|
|
}
|
|
|
|
return (x + width);
|
|
}
|
|
|
|
|
|
void
|
|
XAAImageText8NonTEColorExpansion(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
char *chars
|
|
){
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
unsigned long n;
|
|
|
|
if(!REGION_NUM_RECTS(pGC->pCompositeClip))
|
|
return;
|
|
|
|
(*pGC->font->get_glyphs)(pGC->font, (unsigned long)count,
|
|
(unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo);
|
|
|
|
if(n) ImageGlyphBltNonTEColorExpansion(
|
|
infoRec->pScrn, x + pDraw->x, y + pDraw->y,
|
|
pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask,
|
|
pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo);
|
|
}
|
|
|
|
|
|
void
|
|
XAAImageText16NonTEColorExpansion(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
unsigned short *chars
|
|
){
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
unsigned long n;
|
|
|
|
if(!REGION_NUM_RECTS(pGC->pCompositeClip))
|
|
return;
|
|
|
|
(*pGC->font->get_glyphs)(
|
|
pGC->font, (unsigned long)count, (unsigned char *)chars,
|
|
(FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
|
|
&n, infoRec->CharInfo);
|
|
|
|
if(n) ImageGlyphBltNonTEColorExpansion(
|
|
infoRec->pScrn, x + pDraw->x, y + pDraw->y,
|
|
pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask,
|
|
pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo);
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
GC level replacements for ImageGlyphBlt and PolyGlyphBlt for
|
|
NonTE fonts when using color expansion.
|
|
|
|
********************************************************************/
|
|
|
|
|
|
void
|
|
XAAImageGlyphBltNonTEColorExpansion(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int xInit, int yInit,
|
|
unsigned int nglyph,
|
|
CharInfoPtr *ppci, /* array of character info */
|
|
pointer pglyphBase /* start of array of glyphs */
|
|
){
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
|
|
if(!REGION_NUM_RECTS(pGC->pCompositeClip))
|
|
return;
|
|
|
|
ImageGlyphBltNonTEColorExpansion(
|
|
infoRec->pScrn, xInit + pDraw->x, yInit + pDraw->y,
|
|
pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask,
|
|
pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci);
|
|
}
|
|
|
|
void
|
|
XAAPolyGlyphBltNonTEColorExpansion(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int xInit, int yInit,
|
|
unsigned int nglyph,
|
|
CharInfoPtr *ppci, /* array of character info */
|
|
pointer pglyphBase /* start of array of glyphs */
|
|
){
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
|
|
|
|
if(!REGION_NUM_RECTS(pGC->pCompositeClip))
|
|
return;
|
|
|
|
PolyGlyphBltNonTEColorExpansion(
|
|
infoRec->pScrn, xInit + pDraw->x, yInit + pDraw->y,
|
|
pGC->font, pGC->fgPixel, pGC->alu, pGC->planemask,
|
|
pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci);
|
|
}
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
ImageGlyphBltNonTEColorExpansion -
|
|
PolyGlyphBltNonTEColorExpansion -
|
|
|
|
These guys compute the clipped pieces of text and send it to
|
|
the lower-level function which will handle acceleration of
|
|
arbitrarily clipped text.
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
static int
|
|
CollectCharacterInfo(
|
|
NonTEGlyphPtr glyphs,
|
|
unsigned int nglyph,
|
|
CharInfoPtr *ppci,
|
|
FontPtr pfont
|
|
){
|
|
int i, w = 0;
|
|
|
|
for(i = 0; i < nglyph; i++, ppci++, glyphs++) {
|
|
glyphs->bits = (unsigned char*)((*ppci)->bits);
|
|
glyphs->start = w + (*ppci)->metrics.leftSideBearing;
|
|
glyphs->end = w + (*ppci)->metrics.rightSideBearing;
|
|
glyphs->yoff = (*ppci)->metrics.ascent;
|
|
glyphs->height = glyphs->yoff + (*ppci)->metrics.descent;
|
|
glyphs->srcwidth = PADGLYPHWIDTHBYTES(glyphs->end - glyphs->start);
|
|
w += (*ppci)->metrics.characterWidth;
|
|
}
|
|
return w;
|
|
}
|
|
|
|
|
|
static void
|
|
PolyGlyphBltAsSingleBitmap (
|
|
ScrnInfoPtr pScrn,
|
|
int nglyph,
|
|
FontPtr font,
|
|
int xInit,
|
|
int yInit,
|
|
int nbox,
|
|
BoxPtr pbox,
|
|
int fg,
|
|
int rop,
|
|
unsigned planemask
|
|
){
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
|
|
CARD32 *block, *pntr, *bits;
|
|
int pitch, topLine, botLine, top, bot, height;
|
|
int Left, Right, Top, Bottom;
|
|
int LeftEdge, RightEdge;
|
|
int bitPitch, shift, size, i, skippix;
|
|
NonTEGlyphPtr glyphs = infoRec->GlyphInfo;
|
|
Bool extra;
|
|
|
|
Left = xInit + infoRec->GlyphInfo[0].start;
|
|
Right = xInit + infoRec->GlyphInfo[nglyph - 1].end;
|
|
Top = yInit - FONTMAXBOUNDS(font,ascent);
|
|
Bottom = yInit + FONTMAXBOUNDS(font,descent);
|
|
|
|
/* get into the first band that may contain part of our string */
|
|
while(nbox && (Top >= pbox->y2)) {
|
|
pbox++; nbox--;
|
|
}
|
|
|
|
if(!nbox) return;
|
|
|
|
pitch = (Right - Left + 31) >> 5;
|
|
size = (pitch << 2) * (Bottom - Top);
|
|
block = (CARD32*)xalloc(size);
|
|
bzero(block, size);
|
|
|
|
topLine = 10000; botLine = -10000;
|
|
|
|
while(nglyph--) {
|
|
top = -glyphs->yoff;
|
|
bot = top + glyphs->height;
|
|
if(top < topLine) topLine = top;
|
|
if(bot > botLine) botLine = bot;
|
|
skippix = glyphs->start - infoRec->GlyphInfo[0].start;
|
|
bits = (CARD32*)glyphs->bits;
|
|
bitPitch = glyphs->srcwidth >> 2;
|
|
pntr = block + ((FONTMAXBOUNDS(font,ascent) + top) * pitch) +
|
|
(skippix >> 5);
|
|
shift = skippix & 31;
|
|
extra = ((shift + glyphs->end - glyphs->start) > 32);
|
|
|
|
for(i = top; i < bot; i++) {
|
|
*pntr |= SHIFT_L(*bits, shift);
|
|
if(extra)
|
|
*(pntr + 1) |= SHIFT_R(*bits,32 - shift);
|
|
pntr += pitch;
|
|
bits += bitPitch;
|
|
}
|
|
|
|
glyphs++;
|
|
}
|
|
|
|
pntr = block + ((FONTMAXBOUNDS(font,ascent) + topLine) * pitch);
|
|
|
|
Top = yInit + topLine;
|
|
Bottom = yInit + botLine;
|
|
|
|
while(nbox && (Top >= pbox->y2)) {
|
|
pbox++; nbox--;
|
|
}
|
|
|
|
while(nbox && (Bottom > pbox->y1)) {
|
|
LeftEdge = max(Left, pbox->x1);
|
|
RightEdge = min(Right, pbox->x2);
|
|
|
|
if(RightEdge > LeftEdge) {
|
|
skippix = LeftEdge - Left;
|
|
topLine = max(Top, pbox->y1);
|
|
botLine = min(Bottom, pbox->y2);
|
|
height = botLine - topLine;
|
|
|
|
if(height > 0)
|
|
(*infoRec->WriteBitmap)(pScrn, LeftEdge, topLine,
|
|
RightEdge - LeftEdge, height,
|
|
(unsigned char*)(pntr + ((topLine - Top) * pitch) +
|
|
(skippix >> 5)),
|
|
pitch << 2, skippix & 31, fg, -1, rop, planemask);
|
|
}
|
|
|
|
nbox--; pbox++;
|
|
}
|
|
|
|
xfree(block);
|
|
}
|
|
|
|
static void
|
|
ImageGlyphBltNonTEColorExpansion(
|
|
ScrnInfoPtr pScrn,
|
|
int xInit, int yInit,
|
|
FontPtr font,
|
|
int fg, int bg,
|
|
unsigned planemask,
|
|
RegionPtr cclip,
|
|
int nglyph,
|
|
unsigned char* gBase,
|
|
CharInfoPtr *ppci
|
|
){
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
|
|
int skippix, skipglyph, width, n, i;
|
|
int Left, Right, Top, Bottom;
|
|
int LeftEdge, RightEdge, ytop, ybot;
|
|
int nbox = REGION_NUM_RECTS(cclip);
|
|
BoxPtr pbox = REGION_RECTS(cclip);
|
|
Bool AlreadySetup = FALSE;
|
|
|
|
width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font);
|
|
|
|
/* find our backing rectangle dimensions */
|
|
Left = xInit;
|
|
Right = Left + width;
|
|
Top = yInit - FONTASCENT(font);
|
|
Bottom = yInit + FONTDESCENT(font);
|
|
|
|
/* get into the first band that may contain part of our box */
|
|
while(nbox && (Top >= pbox->y2)) {
|
|
pbox++; nbox--;
|
|
}
|
|
|
|
while(nbox && (Bottom >= pbox->y1)) {
|
|
/* handle backing rect first */
|
|
LeftEdge = max(Left, pbox->x1);
|
|
RightEdge = min(Right, pbox->x2);
|
|
if(RightEdge > LeftEdge) {
|
|
ytop = max(Top, pbox->y1);
|
|
ybot = min(Bottom, pbox->y2);
|
|
|
|
if(ybot > ytop) {
|
|
if(!AlreadySetup) {
|
|
(*infoRec->SetupForSolidFill)(pScrn, bg, GXcopy, planemask);
|
|
AlreadySetup = TRUE;
|
|
}
|
|
(*infoRec->SubsequentSolidFillRect)(pScrn,
|
|
LeftEdge, ytop, RightEdge - LeftEdge, ybot - ytop);
|
|
}
|
|
}
|
|
nbox--; pbox++;
|
|
}
|
|
|
|
nbox = REGION_NUM_RECTS(cclip);
|
|
pbox = REGION_RECTS(cclip);
|
|
|
|
if(infoRec->WriteBitmap && (nglyph > 1) &&
|
|
((FONTMAXBOUNDS(font, rightSideBearing) -
|
|
FONTMINBOUNDS(font, leftSideBearing)) <= 32))
|
|
{
|
|
PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font,
|
|
xInit, yInit, nbox, pbox,
|
|
fg, GXcopy, planemask);
|
|
|
|
return;
|
|
}
|
|
|
|
/* compute an approximate but covering bounding box */
|
|
Left = xInit + infoRec->GlyphInfo[0].start;
|
|
Right = xInit + infoRec->GlyphInfo[nglyph - 1].end;
|
|
Top = yInit - FONTMAXBOUNDS(font,ascent);
|
|
Bottom = yInit + FONTMAXBOUNDS(font,descent);
|
|
|
|
/* get into the first band that may contain part of our box */
|
|
while(nbox && (Top >= pbox->y2)) {
|
|
pbox++; nbox--;
|
|
}
|
|
|
|
/* stop when the lower edge of the box is beyond our string */
|
|
while(nbox && (Bottom >= pbox->y1)) {
|
|
LeftEdge = max(Left, pbox->x1);
|
|
RightEdge = min(Right, pbox->x2);
|
|
|
|
if(RightEdge > LeftEdge) { /* we're possibly drawing something */
|
|
ytop = max(Top, pbox->y1);
|
|
ybot = min(Bottom, pbox->y2);
|
|
if(ybot > ytop) {
|
|
skippix = LeftEdge - xInit;
|
|
skipglyph = 0;
|
|
while(skippix >= infoRec->GlyphInfo[skipglyph].end)
|
|
skipglyph++;
|
|
|
|
skippix = RightEdge - xInit;
|
|
n = 0; i = skipglyph;
|
|
while((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) {
|
|
i++; n++;
|
|
}
|
|
|
|
if(n) (*infoRec->NonTEGlyphRenderer)(pScrn,
|
|
xInit, yInit, n, infoRec->GlyphInfo + skipglyph,
|
|
pbox, fg, GXcopy, planemask);
|
|
}
|
|
}
|
|
|
|
nbox--; pbox++;
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
PolyGlyphBltNonTEColorExpansion(
|
|
ScrnInfoPtr pScrn,
|
|
int xInit, int yInit,
|
|
FontPtr font,
|
|
int fg, int rop,
|
|
unsigned planemask,
|
|
RegionPtr cclip,
|
|
int nglyph,
|
|
unsigned char* gBase,
|
|
CharInfoPtr *ppci
|
|
){
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
|
|
int skippix, skipglyph, width, n, i;
|
|
int Left, Right, Top, Bottom;
|
|
int LeftEdge, RightEdge;
|
|
int nbox = REGION_NUM_RECTS(cclip);
|
|
BoxPtr pbox = REGION_RECTS(cclip);
|
|
|
|
width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font);
|
|
|
|
if(!nbox)
|
|
return width;
|
|
|
|
if((infoRec->WriteBitmap) && (rop == GXcopy) && (nglyph > 1) &&
|
|
((FONTMAXBOUNDS(font, rightSideBearing) -
|
|
FONTMINBOUNDS(font, leftSideBearing)) <= 32)) {
|
|
|
|
PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font,
|
|
xInit, yInit, nbox, pbox,
|
|
fg, rop, planemask);
|
|
|
|
return width;
|
|
}
|
|
|
|
/* compute an approximate but covering bounding box */
|
|
Left = xInit + infoRec->GlyphInfo[0].start;
|
|
Right = xInit + infoRec->GlyphInfo[nglyph - 1].end;
|
|
Top = yInit - FONTMAXBOUNDS(font,ascent);
|
|
Bottom = yInit + FONTMAXBOUNDS(font,descent);
|
|
|
|
/* get into the first band that may contain part of our string */
|
|
while(nbox && (Top >= pbox->y2)) {
|
|
pbox++; nbox--;
|
|
}
|
|
|
|
/* stop when the lower edge of the box is beyond our string */
|
|
while(nbox && (Bottom >= pbox->y1)) {
|
|
LeftEdge = max(Left, pbox->x1);
|
|
RightEdge = min(Right, pbox->x2);
|
|
|
|
if(RightEdge > LeftEdge) { /* we're possibly drawing something */
|
|
|
|
skippix = LeftEdge - xInit;
|
|
skipglyph = 0;
|
|
while(skippix >= infoRec->GlyphInfo[skipglyph].end)
|
|
skipglyph++;
|
|
|
|
skippix = RightEdge - xInit;
|
|
n = 0; i = skipglyph;
|
|
while((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) {
|
|
i++; n++;
|
|
}
|
|
|
|
if(n) (*infoRec->NonTEGlyphRenderer)(pScrn,
|
|
xInit, yInit, n, infoRec->GlyphInfo + skipglyph,
|
|
pbox, fg, rop, planemask);
|
|
}
|
|
|
|
nbox--; pbox++;
|
|
}
|
|
return width;
|
|
}
|
|
|
|
|
|
/* It is possible that the none of the glyphs passed to the
|
|
NonTEGlyphRenderer will be drawn. This function being called
|
|
indicates that part of the text string's bounding box is visible
|
|
but not necessarily that any of the characters are visible */
|
|
|
|
void XAANonTEGlyphRenderer(
|
|
ScrnInfoPtr pScrn,
|
|
int x, int y, int n,
|
|
NonTEGlyphPtr glyphs,
|
|
BoxPtr pbox,
|
|
int fg, int rop,
|
|
unsigned int planemask
|
|
){
|
|
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
|
|
int x1, x2, y1, y2, i, w, h, skipleft, skiptop;
|
|
unsigned char *src;
|
|
|
|
for(i = 0; i < n; i++, glyphs++) {
|
|
x1 = x + glyphs->start;
|
|
x2 = x + glyphs->end;
|
|
y1 = y - glyphs->yoff;
|
|
y2 = y1 + glyphs->height;
|
|
|
|
if(y1 < pbox->y1) {
|
|
skiptop = pbox->y1 - y1;
|
|
y1 = pbox->y1;
|
|
} else skiptop = 0;
|
|
if(y2 > pbox->y2) y2 = pbox->y2;
|
|
h = y2 - y1;
|
|
if(h <= 0) continue;
|
|
|
|
if(x1 < pbox->x1) {
|
|
skipleft = pbox->x1 - x1;
|
|
x1 = pbox->x1;
|
|
} else skipleft = 0;
|
|
if(x2 > pbox->x2) x2 = pbox->x2;
|
|
|
|
w = x2 - x1;
|
|
|
|
if(w > 0) {
|
|
src = glyphs->bits + (skiptop * glyphs->srcwidth);
|
|
|
|
if(skipleft) {
|
|
src += (skipleft >> 5) << 2;
|
|
skipleft &= 31;
|
|
}
|
|
|
|
(*infoRec->WriteBitmap)(pScrn, x1, y1, w, h, src,
|
|
glyphs->srcwidth, skipleft, fg, -1, rop, planemask);
|
|
}
|
|
}
|
|
|
|
}
|