1706f2543Smrg
2706f2543Smrg/********************************************************************
3706f2543Smrg
4706f2543Smrg   In this file we have GC level replacements for PolyText8/16,
5706f2543Smrg   ImageText8/16, ImageGlyphBlt and PolyGlyphBlt for NonTE (proportional)
6706f2543Smrg   fonts. The idea is that everything in this file is device independent.
7706f2543Smrg   The mentioned GCOps are merely wrappers for the
8706f2543Smrg   PolyGlyphBltNonTEColorExpansion and ImageGlyphBltNonTEColorExpansion
9706f2543Smrg   functions which calculate the boxes containing arbitrarily clipped
10706f2543Smrg   text and passes them to the NonTEGlyphRenderer which will usually
11706f2543Smrg   be a lower level XAA function which renders these clipped glyphs using
12706f2543Smrg   the basic color expansion functions exported by the chipset driver.
13706f2543Smrg   The NonTEGlyphRenderer itself may optionally be driver supplied to
14706f2543Smrg   facilitate work-arounds/optimizations at a higher level than usual.
15706f2543Smrg
16706f2543Smrg   Written by Mark Vojkovich (mvojkovi@ucsd.edu)
17706f2543Smrg
18706f2543Smrg********************************************************************/
19706f2543Smrg
20706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
21706f2543Smrg#include <xorg-config.h>
22706f2543Smrg#endif
23706f2543Smrg
24706f2543Smrg#include <string.h>
25706f2543Smrg
26706f2543Smrg#include "misc.h"
27706f2543Smrg#include "xf86.h"
28706f2543Smrg#include "xf86_OSproc.h"
29706f2543Smrg
30706f2543Smrg#include <X11/X.h>
31706f2543Smrg#include <X11/fonts/font.h>
32706f2543Smrg#include "scrnintstr.h"
33706f2543Smrg#include "dixfontstr.h"
34706f2543Smrg#include "xf86str.h"
35706f2543Smrg#include "xaa.h"
36706f2543Smrg#include "xaacexp.h"
37706f2543Smrg#include "xaalocal.h"
38706f2543Smrg#include "gcstruct.h"
39706f2543Smrg#include "pixmapstr.h"
40706f2543Smrg
41706f2543Smrg
42706f2543Smrgstatic void ImageGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn,
43706f2543Smrg				int xInit, int yInit, FontPtr font,
44706f2543Smrg				int fg, int bg, unsigned planemask,
45706f2543Smrg				RegionPtr cclip, int nglyph,
46706f2543Smrg				unsigned char* gBase, CharInfoPtr *ppci);
47706f2543Smrgstatic int PolyGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn,
48706f2543Smrg				int xInit, int yInit, FontPtr font,
49706f2543Smrg				int fg, int rop, unsigned planemask,
50706f2543Smrg				RegionPtr cclip, int nglyph,
51706f2543Smrg				unsigned char* gBase, CharInfoPtr *ppci);
52706f2543Smrg
53706f2543Smrg/********************************************************************
54706f2543Smrg
55706f2543Smrg   GC level replacements for PolyText8/16 and ImageText8/16
56706f2543Smrg   for NonTE fonts when using color expansion.
57706f2543Smrg
58706f2543Smrg********************************************************************/
59706f2543Smrg
60706f2543Smrg
61706f2543Smrgint
62706f2543SmrgXAAPolyText8NonTEColorExpansion(
63706f2543Smrg    DrawablePtr pDraw,
64706f2543Smrg    GCPtr	pGC,
65706f2543Smrg    int		x,
66706f2543Smrg    int 	y,
67706f2543Smrg    int 	count,
68706f2543Smrg    char	*chars )
69706f2543Smrg{
70706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
71706f2543Smrg    unsigned long n;
72706f2543Smrg    int width = 0;
73706f2543Smrg
74706f2543Smrg    (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count,
75706f2543Smrg		(unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo);
76706f2543Smrg
77706f2543Smrg    if(n) {
78706f2543Smrg	width = PolyGlyphBltNonTEColorExpansion( infoRec->pScrn,
79706f2543Smrg		x + pDraw->x, y + pDraw->y, pGC->font,
80706f2543Smrg		pGC->fgPixel, pGC->alu, pGC->planemask,
81706f2543Smrg		pGC->pCompositeClip, n, FONTGLYPHS(pGC->font),
82706f2543Smrg 		infoRec->CharInfo);
83706f2543Smrg    }
84706f2543Smrg
85706f2543Smrg    return x + width;
86706f2543Smrg}
87706f2543Smrg
88706f2543Smrg
89706f2543Smrgint
90706f2543SmrgXAAPolyText16NonTEColorExpansion(
91706f2543Smrg    DrawablePtr pDraw,
92706f2543Smrg    GCPtr	pGC,
93706f2543Smrg    int		x,
94706f2543Smrg    int		y,
95706f2543Smrg    int		count,
96706f2543Smrg    unsigned short *chars )
97706f2543Smrg{
98706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
99706f2543Smrg    unsigned long n;
100706f2543Smrg    int width = 0;
101706f2543Smrg
102706f2543Smrg    (*pGC->font->get_glyphs)(
103706f2543Smrg		pGC->font, (unsigned long)count, (unsigned char *)chars,
104706f2543Smrg		(FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
105706f2543Smrg		&n, infoRec->CharInfo);
106706f2543Smrg
107706f2543Smrg    if(n) {
108706f2543Smrg	width = PolyGlyphBltNonTEColorExpansion( infoRec->pScrn,
109706f2543Smrg		x + pDraw->x, y + pDraw->y, pGC->font,
110706f2543Smrg		pGC->fgPixel, pGC->alu, pGC->planemask,
111706f2543Smrg		pGC->pCompositeClip, n, FONTGLYPHS(pGC->font),
112706f2543Smrg		infoRec->CharInfo);
113706f2543Smrg    }
114706f2543Smrg
115706f2543Smrg    return x + width;
116706f2543Smrg}
117706f2543Smrg
118706f2543Smrg
119706f2543Smrgvoid
120706f2543SmrgXAAImageText8NonTEColorExpansion(
121706f2543Smrg    DrawablePtr pDraw,
122706f2543Smrg    GCPtr	pGC,
123706f2543Smrg    int		x,
124706f2543Smrg    int		y,
125706f2543Smrg    int		count,
126706f2543Smrg    char	*chars
127706f2543Smrg){
128706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
129706f2543Smrg    unsigned long n;
130706f2543Smrg
131706f2543Smrg    if(!RegionNumRects(pGC->pCompositeClip))
132706f2543Smrg	return;
133706f2543Smrg
134706f2543Smrg    (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count,
135706f2543Smrg		(unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo);
136706f2543Smrg
137706f2543Smrg    if(n) ImageGlyphBltNonTEColorExpansion(
138706f2543Smrg	infoRec->pScrn, x + pDraw->x, y + pDraw->y,
139706f2543Smrg	pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask,
140706f2543Smrg	pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo);
141706f2543Smrg}
142706f2543Smrg
143706f2543Smrg
144706f2543Smrgvoid
145706f2543SmrgXAAImageText16NonTEColorExpansion(
146706f2543Smrg    DrawablePtr pDraw,
147706f2543Smrg    GCPtr	pGC,
148706f2543Smrg    int		x,
149706f2543Smrg    int		y,
150706f2543Smrg    int		count,
151706f2543Smrg    unsigned short *chars
152706f2543Smrg){
153706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
154706f2543Smrg    unsigned long n;
155706f2543Smrg
156706f2543Smrg    if(!RegionNumRects(pGC->pCompositeClip))
157706f2543Smrg	return;
158706f2543Smrg
159706f2543Smrg    (*pGC->font->get_glyphs)(
160706f2543Smrg		pGC->font, (unsigned long)count, (unsigned char *)chars,
161706f2543Smrg		(FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
162706f2543Smrg		&n, infoRec->CharInfo);
163706f2543Smrg
164706f2543Smrg    if(n) ImageGlyphBltNonTEColorExpansion(
165706f2543Smrg	infoRec->pScrn, x + pDraw->x, y + pDraw->y,
166706f2543Smrg	pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask,
167706f2543Smrg	pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo);
168706f2543Smrg}
169706f2543Smrg
170706f2543Smrg
171706f2543Smrg
172706f2543Smrg/********************************************************************
173706f2543Smrg
174706f2543Smrg   GC level replacements for ImageGlyphBlt and PolyGlyphBlt for
175706f2543Smrg   NonTE fonts when using color expansion.
176706f2543Smrg
177706f2543Smrg********************************************************************/
178706f2543Smrg
179706f2543Smrg
180706f2543Smrgvoid
181706f2543SmrgXAAImageGlyphBltNonTEColorExpansion(
182706f2543Smrg    DrawablePtr pDraw,
183706f2543Smrg    GCPtr pGC,
184706f2543Smrg    int xInit, int yInit,
185706f2543Smrg    unsigned int nglyph,
186706f2543Smrg    CharInfoPtr *ppci,      /* array of character info */
187706f2543Smrg    pointer pglyphBase	       /* start of array of glyphs */
188706f2543Smrg){
189706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
190706f2543Smrg
191706f2543Smrg    if(!RegionNumRects(pGC->pCompositeClip))
192706f2543Smrg	return;
193706f2543Smrg
194706f2543Smrg    ImageGlyphBltNonTEColorExpansion(
195706f2543Smrg	infoRec->pScrn, xInit + pDraw->x, yInit + pDraw->y,
196706f2543Smrg	pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask,
197706f2543Smrg	pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci);
198706f2543Smrg}
199706f2543Smrg
200706f2543Smrgvoid
201706f2543SmrgXAAPolyGlyphBltNonTEColorExpansion(
202706f2543Smrg    DrawablePtr pDraw,
203706f2543Smrg    GCPtr pGC,
204706f2543Smrg    int xInit, int yInit,
205706f2543Smrg    unsigned int nglyph,
206706f2543Smrg    CharInfoPtr *ppci,      /* array of character info */
207706f2543Smrg    pointer pglyphBase	       /* start of array of glyphs */
208706f2543Smrg){
209706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
210706f2543Smrg
211706f2543Smrg    if(!RegionNumRects(pGC->pCompositeClip))
212706f2543Smrg	return;
213706f2543Smrg
214706f2543Smrg    PolyGlyphBltNonTEColorExpansion(
215706f2543Smrg	infoRec->pScrn, xInit + pDraw->x, yInit + pDraw->y,
216706f2543Smrg	pGC->font, pGC->fgPixel, pGC->alu, pGC->planemask,
217706f2543Smrg	pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci);
218706f2543Smrg}
219706f2543Smrg
220706f2543Smrg
221706f2543Smrg
222706f2543Smrg
223706f2543Smrg/********************************************************************
224706f2543Smrg
225706f2543Smrg   ImageGlyphBltNonTEColorExpansion -
226706f2543Smrg   PolyGlyphBltNonTEColorExpansion -
227706f2543Smrg
228706f2543Smrg   These guys compute the clipped pieces of text and send it to
229706f2543Smrg   the lower-level function which will handle acceleration of
230706f2543Smrg   arbitrarily clipped text.
231706f2543Smrg
232706f2543Smrg********************************************************************/
233706f2543Smrg
234706f2543Smrg
235706f2543Smrg
236706f2543Smrgstatic int
237706f2543SmrgCollectCharacterInfo(
238706f2543Smrg    NonTEGlyphPtr glyphs,
239706f2543Smrg    unsigned int nglyph,
240706f2543Smrg    CharInfoPtr *ppci,
241706f2543Smrg    FontPtr pfont
242706f2543Smrg){
243706f2543Smrg   int i, w = 0;
244706f2543Smrg
245706f2543Smrg   for(i = 0; i < nglyph; i++, ppci++, glyphs++) {
246706f2543Smrg	glyphs->bits = (unsigned char*)((*ppci)->bits);
247706f2543Smrg	glyphs->start = w + (*ppci)->metrics.leftSideBearing;
248706f2543Smrg	glyphs->end = w + (*ppci)->metrics.rightSideBearing;
249706f2543Smrg	glyphs->yoff = (*ppci)->metrics.ascent;
250706f2543Smrg	glyphs->height = glyphs->yoff + (*ppci)->metrics.descent;
251706f2543Smrg	glyphs->srcwidth = PADGLYPHWIDTHBYTES(glyphs->end - glyphs->start);
252706f2543Smrg	w += (*ppci)->metrics.characterWidth;
253706f2543Smrg   }
254706f2543Smrg   return w;
255706f2543Smrg}
256706f2543Smrg
257706f2543Smrg
258706f2543Smrgstatic void
259706f2543SmrgPolyGlyphBltAsSingleBitmap (
260706f2543Smrg   ScrnInfoPtr pScrn,
261706f2543Smrg   int nglyph,
262706f2543Smrg   FontPtr font,
263706f2543Smrg   int xInit,
264706f2543Smrg   int yInit,
265706f2543Smrg   int nbox,
266706f2543Smrg   BoxPtr pbox,
267706f2543Smrg   int fg,
268706f2543Smrg   int rop,
269706f2543Smrg   unsigned planemask
270706f2543Smrg){
271706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
272706f2543Smrg    CARD32 *block, *pntr, *bits;
273706f2543Smrg    int pitch, topLine, botLine, top, bot, height;
274706f2543Smrg    int Left, Right, Top, Bottom;
275706f2543Smrg    int LeftEdge, RightEdge;
276706f2543Smrg    int bitPitch, shift, size, i, skippix;
277706f2543Smrg    NonTEGlyphPtr glyphs = infoRec->GlyphInfo;
278706f2543Smrg    Bool extra;
279706f2543Smrg
280706f2543Smrg    Left = xInit + infoRec->GlyphInfo[0].start;
281706f2543Smrg    Right = xInit + infoRec->GlyphInfo[nglyph - 1].end;
282706f2543Smrg    Top = yInit - FONTMAXBOUNDS(font,ascent);
283706f2543Smrg    Bottom = yInit + FONTMAXBOUNDS(font,descent);
284706f2543Smrg
285706f2543Smrg    /* get into the first band that may contain part of our string */
286706f2543Smrg    while(nbox && (Top >= pbox->y2)) {
287706f2543Smrg	pbox++; nbox--;
288706f2543Smrg    }
289706f2543Smrg
290706f2543Smrg    if(!nbox) return;
291706f2543Smrg
292706f2543Smrg    pitch = (Right - Left + 31) >> 5;
293706f2543Smrg    size = (pitch << 2) * (Bottom - Top);
294706f2543Smrg    block = calloc(1, size);
295706f2543Smrg
296706f2543Smrg    topLine = 10000; botLine = -10000;
297706f2543Smrg
298706f2543Smrg    while(nglyph--) {
299706f2543Smrg	top = -glyphs->yoff;
300706f2543Smrg	bot = top + glyphs->height;
301706f2543Smrg	if(top < topLine) topLine = top;
302706f2543Smrg	if(bot > botLine) botLine = bot;
303706f2543Smrg	skippix = glyphs->start - infoRec->GlyphInfo[0].start;
304706f2543Smrg	bits = (CARD32*)glyphs->bits;
305706f2543Smrg	bitPitch = glyphs->srcwidth >> 2;
306706f2543Smrg	pntr = block + ((FONTMAXBOUNDS(font,ascent) + top) * pitch) +
307706f2543Smrg				(skippix >> 5);
308706f2543Smrg	shift = skippix & 31;
309706f2543Smrg	extra = ((shift + glyphs->end - glyphs->start) > 32);
310706f2543Smrg
311706f2543Smrg	for(i = top; i < bot; i++) {
312706f2543Smrg	    *pntr |= SHIFT_L(*bits, shift);
313706f2543Smrg	    if(extra)
314706f2543Smrg		*(pntr + 1) |= SHIFT_R(*bits,32 - shift);
315706f2543Smrg	    pntr += pitch;
316706f2543Smrg	    bits += bitPitch;
317706f2543Smrg	}
318706f2543Smrg
319706f2543Smrg	glyphs++;
320706f2543Smrg    }
321706f2543Smrg
322706f2543Smrg    pntr = block + ((FONTMAXBOUNDS(font,ascent) + topLine) * pitch);
323706f2543Smrg
324706f2543Smrg    Top = yInit + topLine;
325706f2543Smrg    Bottom = yInit + botLine;
326706f2543Smrg
327706f2543Smrg    while(nbox && (Top >= pbox->y2)) {
328706f2543Smrg	pbox++; nbox--;
329706f2543Smrg    }
330706f2543Smrg
331706f2543Smrg    while(nbox && (Bottom > pbox->y1)) {
332706f2543Smrg	LeftEdge = max(Left, pbox->x1);
333706f2543Smrg	RightEdge = min(Right, pbox->x2);
334706f2543Smrg
335706f2543Smrg	if(RightEdge > LeftEdge) {
336706f2543Smrg	    skippix = LeftEdge - Left;
337706f2543Smrg	    topLine = max(Top, pbox->y1);
338706f2543Smrg	    botLine = min(Bottom, pbox->y2);
339706f2543Smrg	    height = botLine - topLine;
340706f2543Smrg
341706f2543Smrg	    if(height > 0)
342706f2543Smrg	       (*infoRec->WriteBitmap)(pScrn, LeftEdge, topLine,
343706f2543Smrg			RightEdge - LeftEdge, height,
344706f2543Smrg			(unsigned char*)(pntr + ((topLine - Top) * pitch) +
345706f2543Smrg				(skippix >> 5)),
346706f2543Smrg			pitch << 2, skippix & 31, fg, -1, rop, planemask);
347706f2543Smrg	}
348706f2543Smrg
349706f2543Smrg	nbox--; pbox++;
350706f2543Smrg    }
351706f2543Smrg
352706f2543Smrg    free(block);
353706f2543Smrg}
354706f2543Smrg
355706f2543Smrgstatic void
356706f2543SmrgImageGlyphBltNonTEColorExpansion(
357706f2543Smrg   ScrnInfoPtr pScrn,
358706f2543Smrg   int xInit, int yInit,
359706f2543Smrg   FontPtr font,
360706f2543Smrg   int fg, int bg,
361706f2543Smrg   unsigned planemask,
362706f2543Smrg   RegionPtr cclip,
363706f2543Smrg   int nglyph,
364706f2543Smrg   unsigned char* gBase,
365706f2543Smrg   CharInfoPtr *ppci
366706f2543Smrg){
367706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
368706f2543Smrg    int skippix, skipglyph, width, n, i;
369706f2543Smrg    int Left, Right, Top, Bottom;
370706f2543Smrg    int LeftEdge, RightEdge, ytop, ybot;
371706f2543Smrg    int nbox = RegionNumRects(cclip);
372706f2543Smrg    BoxPtr pbox = RegionRects(cclip);
373706f2543Smrg    Bool AlreadySetup = FALSE;
374706f2543Smrg
375706f2543Smrg    width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font);
376706f2543Smrg
377706f2543Smrg    /* find our backing rectangle dimensions */
378706f2543Smrg    Left = xInit;
379706f2543Smrg    Right = Left + width;
380706f2543Smrg    Top = yInit - FONTASCENT(font);
381706f2543Smrg    Bottom = yInit + FONTDESCENT(font);
382706f2543Smrg
383706f2543Smrg    /* get into the first band that may contain part of our box */
384706f2543Smrg    while(nbox && (Top >= pbox->y2)) {
385706f2543Smrg	pbox++; nbox--;
386706f2543Smrg    }
387706f2543Smrg
388706f2543Smrg    while(nbox && (Bottom >= pbox->y1)) {
389706f2543Smrg	/* handle backing rect first */
390706f2543Smrg	LeftEdge = max(Left, pbox->x1);
391706f2543Smrg	RightEdge = min(Right, pbox->x2);
392706f2543Smrg	if(RightEdge > LeftEdge) {
393706f2543Smrg	    ytop = max(Top, pbox->y1);
394706f2543Smrg	    ybot = min(Bottom, pbox->y2);
395706f2543Smrg
396706f2543Smrg	    if(ybot > ytop) {
397706f2543Smrg		if(!AlreadySetup) {
398706f2543Smrg		   (*infoRec->SetupForSolidFill)(pScrn, bg, GXcopy, planemask);
399706f2543Smrg		   AlreadySetup = TRUE;
400706f2543Smrg		}
401706f2543Smrg		(*infoRec->SubsequentSolidFillRect)(pScrn,
402706f2543Smrg			LeftEdge, ytop, RightEdge - LeftEdge, ybot - ytop);
403706f2543Smrg	    }
404706f2543Smrg	}
405706f2543Smrg	nbox--; pbox++;
406706f2543Smrg    }
407706f2543Smrg
408706f2543Smrg    nbox = RegionNumRects(cclip);
409706f2543Smrg    pbox = RegionRects(cclip);
410706f2543Smrg
411706f2543Smrg    if(infoRec->WriteBitmap && (nglyph > 1) &&
412706f2543Smrg			((FONTMAXBOUNDS(font, rightSideBearing) -
413706f2543Smrg          		FONTMINBOUNDS(font, leftSideBearing)) <= 32))
414706f2543Smrg   {
415706f2543Smrg	PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font,
416706f2543Smrg				xInit, yInit, nbox, pbox,
417706f2543Smrg				fg, GXcopy, planemask);
418706f2543Smrg
419706f2543Smrg	return;
420706f2543Smrg    }
421706f2543Smrg
422706f2543Smrg    /* compute an approximate but covering bounding box */
423706f2543Smrg    Left = xInit + infoRec->GlyphInfo[0].start;
424706f2543Smrg    Right = xInit + infoRec->GlyphInfo[nglyph - 1].end;
425706f2543Smrg    Top = yInit - FONTMAXBOUNDS(font,ascent);
426706f2543Smrg    Bottom = yInit + FONTMAXBOUNDS(font,descent);
427706f2543Smrg
428706f2543Smrg    /* get into the first band that may contain part of our box */
429706f2543Smrg    while(nbox && (Top >= pbox->y2)) {
430706f2543Smrg	pbox++; nbox--;
431706f2543Smrg    }
432706f2543Smrg
433706f2543Smrg    /* stop when the lower edge of the box is beyond our string */
434706f2543Smrg    while(nbox && (Bottom >= pbox->y1)) {
435706f2543Smrg	LeftEdge = max(Left, pbox->x1);
436706f2543Smrg	RightEdge = min(Right, pbox->x2);
437706f2543Smrg
438706f2543Smrg	if(RightEdge > LeftEdge) { /* we're possibly drawing something */
439706f2543Smrg	    ytop = max(Top, pbox->y1);
440706f2543Smrg	    ybot = min(Bottom, pbox->y2);
441706f2543Smrg	    if(ybot > ytop) {
442706f2543Smrg		skippix = LeftEdge - xInit;
443706f2543Smrg		skipglyph = 0;
444706f2543Smrg		while(skippix >= infoRec->GlyphInfo[skipglyph].end)
445706f2543Smrg		   skipglyph++;
446706f2543Smrg
447706f2543Smrg		skippix = RightEdge - xInit;
448706f2543Smrg		n = 0; i = skipglyph;
449706f2543Smrg		while((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) {
450706f2543Smrg		    i++; n++;
451706f2543Smrg		}
452706f2543Smrg
453706f2543Smrg		if(n) (*infoRec->NonTEGlyphRenderer)(pScrn,
454706f2543Smrg			xInit, yInit, n, infoRec->GlyphInfo + skipglyph,
455706f2543Smrg			pbox, fg, GXcopy, planemask);
456706f2543Smrg	    }
457706f2543Smrg	}
458706f2543Smrg
459706f2543Smrg	nbox--; pbox++;
460706f2543Smrg    }
461706f2543Smrg}
462706f2543Smrg
463706f2543Smrg
464706f2543Smrgstatic int
465706f2543SmrgPolyGlyphBltNonTEColorExpansion(
466706f2543Smrg   ScrnInfoPtr pScrn,
467706f2543Smrg   int xInit, int yInit,
468706f2543Smrg   FontPtr font,
469706f2543Smrg   int fg, int rop,
470706f2543Smrg   unsigned planemask,
471706f2543Smrg   RegionPtr cclip,
472706f2543Smrg   int nglyph,
473706f2543Smrg   unsigned char* gBase,
474706f2543Smrg   CharInfoPtr *ppci
475706f2543Smrg){
476706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
477706f2543Smrg    int skippix, skipglyph, width, n, i;
478706f2543Smrg    int Left, Right, Top, Bottom;
479706f2543Smrg    int LeftEdge, RightEdge;
480706f2543Smrg    int nbox = RegionNumRects(cclip);
481706f2543Smrg    BoxPtr pbox = RegionRects(cclip);
482706f2543Smrg
483706f2543Smrg    width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font);
484706f2543Smrg
485706f2543Smrg    if(!nbox)
486706f2543Smrg	return width;
487706f2543Smrg
488706f2543Smrg    if((infoRec->WriteBitmap) && (rop == GXcopy) && (nglyph > 1) &&
489706f2543Smrg	((FONTMAXBOUNDS(font, rightSideBearing) -
490706f2543Smrg          FONTMINBOUNDS(font, leftSideBearing)) <= 32)) {
491706f2543Smrg
492706f2543Smrg	 PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font,
493706f2543Smrg				xInit, yInit, nbox, pbox,
494706f2543Smrg				fg, rop, planemask);
495706f2543Smrg
496706f2543Smrg	return width;
497706f2543Smrg    }
498706f2543Smrg
499706f2543Smrg    /* compute an approximate but covering bounding box */
500706f2543Smrg    Left = xInit + infoRec->GlyphInfo[0].start;
501706f2543Smrg    Right = xInit + infoRec->GlyphInfo[nglyph - 1].end;
502706f2543Smrg    Top = yInit - FONTMAXBOUNDS(font,ascent);
503706f2543Smrg    Bottom = yInit + FONTMAXBOUNDS(font,descent);
504706f2543Smrg
505706f2543Smrg    /* get into the first band that may contain part of our string */
506706f2543Smrg    while(nbox && (Top >= pbox->y2)) {
507706f2543Smrg	pbox++; nbox--;
508706f2543Smrg    }
509706f2543Smrg
510706f2543Smrg    /* stop when the lower edge of the box is beyond our string */
511706f2543Smrg    while(nbox && (Bottom >= pbox->y1)) {
512706f2543Smrg	LeftEdge = max(Left, pbox->x1);
513706f2543Smrg	RightEdge = min(Right, pbox->x2);
514706f2543Smrg
515706f2543Smrg	if(RightEdge > LeftEdge) { /* we're possibly drawing something */
516706f2543Smrg
517706f2543Smrg	    skippix = LeftEdge - xInit;
518706f2543Smrg	    skipglyph = 0;
519706f2543Smrg	    while(skippix >= infoRec->GlyphInfo[skipglyph].end)
520706f2543Smrg		skipglyph++;
521706f2543Smrg
522706f2543Smrg	    skippix = RightEdge - xInit;
523706f2543Smrg	    n = 0; i = skipglyph;
524706f2543Smrg	    while((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) {
525706f2543Smrg		i++; n++;
526706f2543Smrg	    }
527706f2543Smrg
528706f2543Smrg	    if(n) (*infoRec->NonTEGlyphRenderer)(pScrn,
529706f2543Smrg			xInit, yInit, n, infoRec->GlyphInfo + skipglyph,
530706f2543Smrg			pbox, fg, rop, planemask);
531706f2543Smrg	}
532706f2543Smrg
533706f2543Smrg	nbox--; pbox++;
534706f2543Smrg    }
535706f2543Smrg    return width;
536706f2543Smrg}
537706f2543Smrg
538706f2543Smrg
539706f2543Smrg/* It is possible that the none of the glyphs passed to the
540706f2543Smrg   NonTEGlyphRenderer will be drawn.  This function being called
541706f2543Smrg   indicates that part of the text string's bounding box is visible
542706f2543Smrg   but not necessarily that any of the characters are visible */
543706f2543Smrg
544706f2543Smrgvoid XAANonTEGlyphRenderer(
545706f2543Smrg   ScrnInfoPtr pScrn,
546706f2543Smrg   int x, int y, int n,
547706f2543Smrg   NonTEGlyphPtr glyphs,
548706f2543Smrg   BoxPtr pbox,
549706f2543Smrg   int fg, int rop,
550706f2543Smrg   unsigned int planemask
551706f2543Smrg){
552706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
553706f2543Smrg    int x1, x2, y1, y2, i, w, h, skipleft, skiptop;
554706f2543Smrg    unsigned char *src;
555706f2543Smrg
556706f2543Smrg    for(i = 0; i < n; i++, glyphs++) {
557706f2543Smrg	x1 = x + glyphs->start;
558706f2543Smrg	x2 = x + glyphs->end;
559706f2543Smrg	y1 = y - glyphs->yoff;
560706f2543Smrg	y2 = y1 + glyphs->height;
561706f2543Smrg
562706f2543Smrg	if(y1 < pbox->y1) {
563706f2543Smrg	    skiptop = pbox->y1 - y1;
564706f2543Smrg	    y1 = pbox->y1;
565706f2543Smrg	} else skiptop = 0;
566706f2543Smrg	if(y2 > pbox->y2) y2 = pbox->y2;
567706f2543Smrg	h = y2 - y1;
568706f2543Smrg	if(h <= 0) continue;
569706f2543Smrg
570706f2543Smrg	if(x1 < pbox->x1) {
571706f2543Smrg	    skipleft = pbox->x1 - x1;
572706f2543Smrg	    x1 = pbox->x1;
573706f2543Smrg	} else skipleft = 0;
574706f2543Smrg	if(x2 > pbox->x2) x2 = pbox->x2;
575706f2543Smrg
576706f2543Smrg	w = x2 - x1;
577706f2543Smrg
578706f2543Smrg	if(w > 0) {
579706f2543Smrg	    src = glyphs->bits + (skiptop * glyphs->srcwidth);
580706f2543Smrg
581706f2543Smrg	    if(skipleft) {
582706f2543Smrg		src += (skipleft >> 5) << 2;
583706f2543Smrg		skipleft &= 31;
584706f2543Smrg	    }
585706f2543Smrg
586706f2543Smrg	    (*infoRec->WriteBitmap)(pScrn, x1, y1, w, h, src,
587706f2543Smrg			glyphs->srcwidth, skipleft, fg, -1, rop, planemask);
588706f2543Smrg	}
589706f2543Smrg    }
590706f2543Smrg
591706f2543Smrg}
592