]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mfb/mfbplygblt.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / mfb / mfbplygblt.c
1 /***********************************************************
2
3 Copyright (c) 1987  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25
26
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29                         All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its 
32 documentation for any purpose and without fee is hereby granted, 
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in 
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.  
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 ******************************************************************/
48 /* $XConsortium: mfbplygblt.c,v 5.14 94/04/17 20:28:29 dpw Exp $ */
49 /* $XFree86: xc/programs/Xserver/mfb/mfbplygblt.c,v 3.0 1995/06/14 12:43:48 dawes Exp $ */
50
51 #include "X.h"
52 #include "Xmd.h"
53 #include "Xproto.h"
54 #include "mfb.h"
55 #include "fontstruct.h"
56 #include "dixfontstr.h"
57 #include "gcstruct.h"
58 #include "windowstr.h"
59 #include "pixmapstr.h"
60 #include "scrnintstr.h"
61 #include "regionstr.h"
62 #include "maskbits.h"
63 #include "miscstruct.h"
64
65 /*
66     we should eventually special-case fixed-width fonts, although
67 its more important for ImageText, which is meant for terminal
68 emulators.
69
70     this works for fonts with glyphs <= 32 bits wide.
71
72     the clipping calculations are done for worst-case fonts.
73 we make no assumptions about the heights, widths, or bearings
74 of the glyphs.  if we knew that the glyphs are all the same height,
75 we could clip the tops and bottoms per clipping box, rather
76 than per character per clipping box.  if we knew that the glyphs'
77 left and right bearings were well-behaved, we could clip a single
78 character at the start, output until the last unclipped
79 character, and then clip the last one.  this is all straightforward
80 to determine based on max-bounds and min-bounds from the font.
81     there is some inefficiency introduced in the per-character
82 clipping to make what's going on clearer.
83
84     (it is possible, for example, for a font to be defined in which the
85 next-to-last character in a font would be clipped out, but the last
86 one wouldn't.  the code below deals with this.)
87
88     PolyText looks at the fg color and the rasterop; mfbValidateGC
89 swaps in the right routine after looking at the reduced ratserop
90 in the private field of the GC.  
91
92    the register allocations are provisional; in particualr startmask and
93 endmask might not be the right things.  pglyph, xoff, pdst, and tmpSrc
94 are fairly obvious, though.
95
96    to avoid source proliferation, this file is compiled
97 three times:
98         MFBPOLYGLYPHBLT         OPEQ
99         mfbPolyGlyphBltWhite    |=
100         mfbPolyGlyphBltBlack    &=~
101         mfbPolyGlyphBltInvert   ^=
102 */
103
104 void
105 MFBPOLYGLYPHBLT(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
106     DrawablePtr pDrawable;
107     GCPtr       pGC;
108     int         x, y;
109     unsigned int nglyph;
110     CharInfoPtr *ppci;          /* array of character info */
111     pointer     pglyphBase;     /* start of array of glyphs (unused in R5) */
112 {
113     ExtentInfoRec info; /* used by QueryGlyphExtents() */
114     BoxRec bbox;                /* string's bounding box */
115
116     CharInfoPtr pci;
117     int xorg, yorg;     /* origin of drawable in bitmap */
118     int widthDst;       /* width of dst in longwords */
119
120                         /* these keep track of the character origin */
121     PixelType *pdstBase;
122                         /* points to longword with character origin */
123     int xchar;          /* xorigin of char (mod 32) */
124
125                         /* these are used for placing the glyph */
126     register int xoff;  /* x offset of left edge of glyph (mod 32) */
127     register PixelType *pdst;
128                         /* pointer to current longword in dst */
129
130     int w;              /* width of glyph in bits */
131     int h;              /* height of glyph */
132     int widthGlyph;     /* width of glyph, in bytes */
133     register unsigned char *pglyph;
134                         /* pointer to current row of glyph */
135
136                         /* used for putting down glyph */
137     register PixelType tmpSrc;
138                         /* for getting bits from glyph */
139     register PixelType startmask;
140     register PixelType endmask;
141     register int nFirst;/* bits of glyph in current longword */
142
143     if (!(pGC->planemask & 1))
144         return;
145
146     xorg = pDrawable->x;
147     yorg = pDrawable->y;
148     mfbGetPixelWidthAndPointer(pDrawable, widthDst, pdstBase);
149
150     x += xorg;
151     y += yorg;
152
153     QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info);
154     bbox.x1 = x + info.overallLeft;
155     bbox.x2 = x + info.overallRight;
156     bbox.y1 = y - info.overallAscent;
157     bbox.y2 = y + info.overallDescent;
158
159     switch (RECT_IN_REGION(pGC->pScreen, 
160            ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip, &bbox))
161     {
162       case rgnOUT:
163         break;
164       case rgnIN:
165         pdstBase = mfbScanlineNoBankSwitch(pdstBase, x, y, widthDst);
166         xchar = x & PIM;
167
168         while(nglyph--)
169         {
170             pci = *ppci;
171             pglyph = FONTGLYPHBITS(pglyphBase, pci);
172             w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
173             h = pci->metrics.ascent + pci->metrics.descent;
174             widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
175
176             /* start at top scanline of glyph */
177             pdst = pdstBase;
178
179             /* find correct word in scanline and x offset within it
180                for left edge of glyph
181             */
182             xoff = xchar + pci->metrics.leftSideBearing;
183             if (xoff > PLST)
184             {
185                 pdst++;
186                 xoff &= PIM;
187             }
188             else if (xoff < 0)
189             {
190                 xoff += PPW;
191                 pdst--;
192             }
193
194             pdst = mfbScanlineDelta(pdst, -pci->metrics.ascent, widthDst);
195
196             if ((xoff + w) <= PPW)
197             {
198                 /* glyph all in one longword */
199                 maskpartialbits(xoff, w, startmask);
200                 while (h--)
201                 {
202                     getleftbits(pglyph, w, tmpSrc);
203                     *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
204                     pglyph += widthGlyph;
205                     mfbScanlineInc(pdst, widthDst);
206                 }
207             }
208             else
209             {
210                 /* glyph crosses longword boundary */
211                 maskPPWbits(xoff, w, startmask, endmask);
212                 nFirst = PPW - xoff;
213                 while (h--)
214                 {
215                     getleftbits(pglyph, w, tmpSrc);
216                     *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
217                     *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask);
218                     pglyph += widthGlyph;
219                     mfbScanlineInc(pdst, widthDst);
220                 }
221             } /* glyph crosses longwords boundary */
222
223             /* update character origin */
224             x += pci->metrics.characterWidth;
225             xchar += pci->metrics.characterWidth;
226             if (xchar > PLST)
227             {
228                 xchar -= PPW;
229                 pdstBase++;
230             }
231             else if (xchar < 0)
232             {
233                 xchar += PPW;
234                 pdstBase--;
235             }
236             ppci++;
237         } /* while nglyph-- */
238         break;
239       case rgnPART:
240       {
241         TEXTPOS *ppos;
242         RegionPtr cclip;
243         int nbox;
244         BoxPtr pbox;
245         int xpos;               /* x position of char origin */
246         int i;
247         BoxRec clip;
248         int leftEdge, rightEdge;
249         int topEdge, bottomEdge;
250         int glyphRow;           /* first row of glyph not wholly
251                                    clipped out */
252         int glyphCol;           /* leftmost visible column of glyph */
253         int getWidth;           /* bits to get from glyph */
254
255         if(!(ppos = (TEXTPOS *)ALLOCATE_LOCAL(nglyph * sizeof(TEXTPOS))))
256             return;
257
258         pdstBase = mfbScanlineNoBankSwitch(pdstBase, x, y, widthDst);
259         xpos = x;
260         xchar = xpos & PIM;
261
262         for (i=0; i<nglyph; i++)
263         {
264             pci = ppci[i];
265
266             ppos[i].xpos = xpos;
267             ppos[i].xchar = xchar;
268             ppos[i].leftEdge = xpos + pci->metrics.leftSideBearing;
269             ppos[i].rightEdge = xpos + pci->metrics.rightSideBearing;
270             ppos[i].topEdge = y - pci->metrics.ascent;
271             ppos[i].bottomEdge = y + pci->metrics.descent;
272             ppos[i].pdstBase = pdstBase;
273             ppos[i].widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
274
275             xpos += pci->metrics.characterWidth;
276             xchar += pci->metrics.characterWidth;
277             if (xchar > PLST)
278             {
279                 xchar &= PIM;
280                 pdstBase++;
281             }
282             else if (xchar < 0)
283             {
284                 xchar += PPW;
285                 pdstBase--;
286             }
287         }
288
289         cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
290         pbox = REGION_RECTS(cclip);
291         nbox = REGION_NUM_RECTS(cclip);
292
293         for (; --nbox >= 0; pbox++)
294         {
295             clip.x1 = max(bbox.x1, pbox->x1);
296             clip.y1 = max(bbox.y1, pbox->y1);
297             clip.x2 = min(bbox.x2, pbox->x2);
298             clip.y2 = min(bbox.y2, pbox->y2);
299             if ((clip.x2<=clip.x1) || (clip.y2<=clip.y1))
300                 continue;
301
302             for(i=0; i<nglyph; i++)
303             {
304                 pci = ppci[i];
305                 xchar = ppos[i].xchar;
306
307                 /* clip the left and right edges */
308                 if (ppos[i].leftEdge < clip.x1)
309                     leftEdge = clip.x1;
310                 else
311                     leftEdge = ppos[i].leftEdge;
312
313                 if (ppos[i].rightEdge > clip.x2)
314                     rightEdge = clip.x2;
315                 else
316                     rightEdge = ppos[i].rightEdge;
317
318                 w = rightEdge - leftEdge;
319                 if (w <= 0)
320                     continue;
321
322                 /* clip the top and bottom edges */
323                 if (ppos[i].topEdge < clip.y1)
324                     topEdge = clip.y1;
325                 else
326                     topEdge = ppos[i].topEdge;
327
328                 if (ppos[i].bottomEdge > clip.y2)
329                     bottomEdge = clip.y2;
330                 else
331                     bottomEdge = ppos[i].bottomEdge;
332
333                 h = bottomEdge - topEdge;
334                 if (h <= 0)
335                     continue;
336
337                 glyphRow = (topEdge - y) + pci->metrics.ascent;
338                 widthGlyph = ppos[i].widthGlyph;
339                 pglyph = FONTGLYPHBITS(pglyphBase, pci);
340                 pglyph += (glyphRow * widthGlyph);
341
342                 pdst = ppos[i].pdstBase;
343
344                 glyphCol = (leftEdge - ppos[i].xpos) -
345                            (pci->metrics.leftSideBearing);
346                 getWidth = w + glyphCol;
347                 xoff = xchar + (leftEdge - ppos[i].xpos);
348                 if (xoff > PLST)
349                 {
350                     xoff &= PIM;
351                     pdst++;
352                 }
353                 else if (xoff < 0)
354                 {
355                     xoff += PPW;
356                     pdst--;
357                 }
358
359                 pdst = mfbScanlineDelta(pdst, -(y-topEdge), widthDst);
360
361                 if ((xoff + w) <= PPW)
362                 {
363                     maskpartialbits(xoff, w, startmask);
364                     while (h--)
365                     {
366                         getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
367                         *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
368                         pglyph += widthGlyph;
369                         mfbScanlineInc(pdst, widthDst);
370                     }
371                 }
372                 else
373                 {
374                     maskPPWbits(xoff, w, startmask, endmask);
375                     nFirst = PPW - xoff;
376                     while (h--)
377                     {
378                         getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
379                         *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
380                         *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask);
381                         pglyph += widthGlyph;
382                         mfbScanlineInc(pdst, widthDst);
383                     }
384                 }
385             } /* for each glyph */
386         } /* while nbox-- */
387         DEALLOCATE_LOCAL(ppos);
388         break;
389       }
390       default:
391         break;
392     }
393 }