103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 1998 Keith Packard
303b705cfSriastradh * Copyright © 2012 Intel Corporation
403b705cfSriastradh *
503b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its
603b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that
703b705cfSriastradh * the above copyright notice appear in all copies and that both that
803b705cfSriastradh * copyright notice and this permission notice appear in supporting
903b705cfSriastradh * documentation, and that the name of Keith Packard not be used in
1003b705cfSriastradh * advertising or publicity pertaining to distribution of the software without
1103b705cfSriastradh * specific, written prior permission.  Keith Packard makes no
1203b705cfSriastradh * representations about the suitability of this software for any purpose.  It
1303b705cfSriastradh * is provided "as is" without express or implied warranty.
1403b705cfSriastradh *
1503b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1603b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1703b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1803b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1903b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2003b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2103b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE.
2203b705cfSriastradh */
2303b705cfSriastradh
2403b705cfSriastradh#include "fb.h"
2503b705cfSriastradh#include <X11/fonts/fontstruct.h>
2603b705cfSriastradh#include <dixfontstr.h>
2703b705cfSriastradh
2803b705cfSriastradh#define GLYPH	    fbGlyph8
2903b705cfSriastradh#define BITS	    BYTE
3003b705cfSriastradh#define BITS2	    CARD16
3103b705cfSriastradh#define BITS4	    CARD32
3203b705cfSriastradh#include "fbglyphbits.h"
3303b705cfSriastradh#undef BITS
3403b705cfSriastradh#undef BITS2
3503b705cfSriastradh#undef BITS4
3603b705cfSriastradh#undef GLYPH
3703b705cfSriastradh
3803b705cfSriastradh#define GLYPH	    fbGlyph16
3903b705cfSriastradh#define BITS	    CARD16
4003b705cfSriastradh#define BITS2	    CARD32
4103b705cfSriastradh#include "fbglyphbits.h"
4203b705cfSriastradh#undef BITS
4303b705cfSriastradh#undef BITS2
4403b705cfSriastradh#undef GLYPH
4503b705cfSriastradh
4603b705cfSriastradh#define GLYPH	    fbGlyph32
4703b705cfSriastradh#define BITS	    CARD32
4803b705cfSriastradh#include "fbglyphbits.h"
4903b705cfSriastradh#undef BITS
5003b705cfSriastradh#undef GLYPH
5103b705cfSriastradh
5203b705cfSriastradhstatic bool
5303b705cfSriastradhfbGlyphIn(GCPtr gc, int x, int y, int width, int height)
5403b705cfSriastradh{
5503b705cfSriastradh	BoxRec box;
5603b705cfSriastradh	BoxPtr extents = RegionExtents(gc->pCompositeClip);
5703b705cfSriastradh
5803b705cfSriastradh	/*
5903b705cfSriastradh	 * Check extents by hand to avoid 16 bit overflows
6003b705cfSriastradh	 */
6103b705cfSriastradh	if (x < (int) extents->x1 || (int) extents->x2 < x + width)
6203b705cfSriastradh		return FALSE;
6303b705cfSriastradh	if (y < (int) extents->y1 || (int) extents->y2 < y + height)
6403b705cfSriastradh		return FALSE;
6503b705cfSriastradh
6603b705cfSriastradh	box.x1 = x;
6703b705cfSriastradh	box.x2 = x + width;
6803b705cfSriastradh	box.y1 = y;
6903b705cfSriastradh	box.y2 = y + height;
7003b705cfSriastradh	return RegionContainsRect(gc->pCompositeClip, &box) == rgnIN;
7103b705cfSriastradh}
7203b705cfSriastradh
7303b705cfSriastradh#define WRITE1(d,n,fg)	WRITE((d) + (n), (CARD8) fg)
7403b705cfSriastradh#define WRITE2(d,n,fg)	WRITE((CARD16 *) &(d[n]), (CARD16) fg)
7503b705cfSriastradh#define WRITE4(d,n,fg)	WRITE((CARD32 *) &(d[n]), (CARD32) fg)
7603b705cfSriastradh
7703b705cfSriastradh/*
7803b705cfSriastradh * This is a bit tricky, but it's brief.  Write 12 bytes worth
7903b705cfSriastradh * of dest, which is four pixels, at a time.  This gives constant
8003b705cfSriastradh * code for each pattern as they're always aligned the same
8103b705cfSriastradh *
8203b705cfSriastradh *  a b c d  a b c d  a b c d	bytes
8303b705cfSriastradh *  A B C A  B C A B  C A B C	pixels
8403b705cfSriastradh *
8503b705cfSriastradh *    f0        f1       f2
8603b705cfSriastradh *  A B C A  B C A B  C A B C	pixels LSB
8703b705cfSriastradh *  C A B C  A B C A  B C A B	pixels MSB
8803b705cfSriastradh *
8903b705cfSriastradh *		LSB	MSB
9003b705cfSriastradh *  A		f0	f1
9103b705cfSriastradh *  B		f1	f2
9203b705cfSriastradh *  C		f2	f0
9303b705cfSriastradh *  A B		f0	f2
9403b705cfSriastradh *  B C		f1	f0
9503b705cfSriastradh *  C A		f2	f1
9603b705cfSriastradh *  A B C A	f0	f1
9703b705cfSriastradh *  B C A B	f1    	f2
9803b705cfSriastradh *  C A B C	f2	f0
9903b705cfSriastradh */
10003b705cfSriastradh
10103b705cfSriastradh#undef _A
10203b705cfSriastradh#undef _B
10303b705cfSriastradh#undef _C
10403b705cfSriastradh#undef _AB
10503b705cfSriastradh#undef _BC
10603b705cfSriastradh#undef _CA
10703b705cfSriastradh#undef _ABCA
10803b705cfSriastradh#undef _BCAB
10903b705cfSriastradh#undef _CABC
11003b705cfSriastradh
11103b705cfSriastradh#define _A	f0
11203b705cfSriastradh#define _B	f1
11303b705cfSriastradh#define _C	f2
11403b705cfSriastradh#define _AB	f0
11503b705cfSriastradh#define _BC	f1
11603b705cfSriastradh#define _CA	f2
11703b705cfSriastradh#define _ABCA	f0
11803b705cfSriastradh#define _BCAB	f1
11903b705cfSriastradh#define _CABC	f2
12003b705cfSriastradh#define CASE(a,b,c,d)	(a | (b << 1) | (c << 2) | (d << 3))
12103b705cfSriastradh
12203b705cfSriastradhvoid
12303b705cfSriastradhfbPolyGlyphBlt(DrawablePtr drawable, GCPtr gc,
12403b705cfSriastradh               int x, int y,
12503b705cfSriastradh               unsigned int nglyph, CharInfoPtr * ppci, pointer glyphs)
12603b705cfSriastradh{
12703b705cfSriastradh	FbGCPrivPtr pgc = fb_gc(gc);
12803b705cfSriastradh	CharInfoPtr pci;
12903b705cfSriastradh	unsigned char *pglyph;      /* pointer bits in glyph */
13003b705cfSriastradh	int gx, gy;
13103b705cfSriastradh	int gWidth, gHeight;        /* width and height of glyph */
13203b705cfSriastradh	FbStride gStride;           /* stride of glyph */
13303b705cfSriastradh	void (*raster) (FbBits *, FbStride, int, FbStip *, FbBits, int, int);
13403b705cfSriastradh	FbBits *dst = 0;
13503b705cfSriastradh	FbStride dstStride = 0;
13603b705cfSriastradh	int dstBpp = 0;
13703b705cfSriastradh	int dstXoff = 0, dstYoff = 0;
13803b705cfSriastradh
13903b705cfSriastradh	DBG(("%s x %d\n", __FUNCTION__, nglyph));
14003b705cfSriastradh
14103b705cfSriastradh	raster = 0;
14203b705cfSriastradh	if (gc->fillStyle == FillSolid && pgc->and == 0) {
14303b705cfSriastradh		dstBpp = drawable->bitsPerPixel;
14403b705cfSriastradh		switch (dstBpp) {
14503b705cfSriastradh		case 8:
14603b705cfSriastradh			raster = fbGlyph8;
14703b705cfSriastradh			break;
14803b705cfSriastradh		case 16:
14903b705cfSriastradh			raster = fbGlyph16;
15003b705cfSriastradh			break;
15103b705cfSriastradh		case 32:
15203b705cfSriastradh			raster = fbGlyph32;
15303b705cfSriastradh			break;
15403b705cfSriastradh		}
15503b705cfSriastradh	}
15603b705cfSriastradh	x += drawable->x;
15703b705cfSriastradh	y += drawable->y;
15803b705cfSriastradh
15903b705cfSriastradh	while (nglyph--) {
16003b705cfSriastradh		pci = *ppci++;
16103b705cfSriastradh		pglyph = FONTGLYPHBITS(glyphs, pci);
16203b705cfSriastradh		gWidth = GLYPHWIDTHPIXELS(pci);
16303b705cfSriastradh		gHeight = GLYPHHEIGHTPIXELS(pci);
16403b705cfSriastradh		if (gWidth && gHeight) {
16503b705cfSriastradh			gx = x + pci->metrics.leftSideBearing;
16603b705cfSriastradh			gy = y - pci->metrics.ascent;
16703b705cfSriastradh			if (raster && gWidth <= sizeof(FbStip) * 8 &&
16803b705cfSriastradh			    fbGlyphIn(gc, gx, gy, gWidth, gHeight)) {
16903b705cfSriastradh				fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff,
17003b705cfSriastradh					      dstYoff);
17103b705cfSriastradh				raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
17203b705cfSriastradh					  (FbStip *) pglyph, pgc->xor, gx + dstXoff, gHeight);
17303b705cfSriastradh			} else {
17403b705cfSriastradh				gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip);
17503b705cfSriastradh				fbPushImage(drawable, gc,
17603b705cfSriastradh					    (FbStip *)pglyph,
17703b705cfSriastradh					    gStride, 0, gx, gy, gWidth, gHeight);
17803b705cfSriastradh			}
17903b705cfSriastradh		}
18003b705cfSriastradh		x += pci->metrics.characterWidth;
18103b705cfSriastradh	}
18203b705cfSriastradh}
18303b705cfSriastradh
18403b705cfSriastradhvoid
18503b705cfSriastradhfbImageGlyphBlt(DrawablePtr drawable, GCPtr gc,
18603b705cfSriastradh                int x, int y,
18703b705cfSriastradh                unsigned int nglyph, CharInfoPtr * ppciInit, pointer glyphs)
18803b705cfSriastradh{
18903b705cfSriastradh	FbGCPrivPtr pgc = fb_gc(gc);
19003b705cfSriastradh	CharInfoPtr *ppci;
19103b705cfSriastradh	CharInfoPtr pci;
19203b705cfSriastradh	unsigned char *pglyph;      /* pointer bits in glyph */
19303b705cfSriastradh	int gWidth, gHeight;        /* width and height of glyph */
19403b705cfSriastradh	FbStride gStride;           /* stride of glyph */
19503b705cfSriastradh	bool opaque;
19603b705cfSriastradh	int n;
19703b705cfSriastradh	int gx, gy;
19803b705cfSriastradh	void (*raster)(FbBits *, FbStride, int, FbStip *, FbBits, int, int);
19903b705cfSriastradh	FbBits *dst = 0;
20003b705cfSriastradh	FbStride dstStride = 0;
20103b705cfSriastradh	int dstBpp = 0;
20203b705cfSriastradh	int dstXoff = 0, dstYoff = 0;
20303b705cfSriastradh
20403b705cfSriastradh	DBG(("%s x %d\n", __FUNCTION__, nglyph));
20503b705cfSriastradh
20603b705cfSriastradh	raster = 0;
20703b705cfSriastradh	if (pgc->and == 0) {
20803b705cfSriastradh		dstBpp = drawable->bitsPerPixel;
20903b705cfSriastradh		switch (dstBpp) {
21003b705cfSriastradh		case 8:
21103b705cfSriastradh			raster = fbGlyph8;
21203b705cfSriastradh			break;
21303b705cfSriastradh		case 16:
21403b705cfSriastradh			raster = fbGlyph16;
21503b705cfSriastradh			break;
21603b705cfSriastradh		case 32:
21703b705cfSriastradh			raster = fbGlyph32;
21803b705cfSriastradh			break;
21903b705cfSriastradh		}
22003b705cfSriastradh	}
22103b705cfSriastradh
22203b705cfSriastradh	x += drawable->x;
22303b705cfSriastradh	y += drawable->y;
22403b705cfSriastradh
22503b705cfSriastradh	if (TERMINALFONT(gc->font) && !raster) {
22603b705cfSriastradh		opaque = TRUE;
22703b705cfSriastradh	} else {
22803b705cfSriastradh		int xBack, widthBack;
22903b705cfSriastradh		int yBack, heightBack;
23003b705cfSriastradh
23103b705cfSriastradh		ppci = ppciInit;
23203b705cfSriastradh		n = nglyph;
23303b705cfSriastradh		widthBack = 0;
23403b705cfSriastradh		while (n--)
23503b705cfSriastradh			widthBack += (*ppci++)->metrics.characterWidth;
23603b705cfSriastradh
23703b705cfSriastradh		xBack = x;
23803b705cfSriastradh		if (widthBack < 0) {
23903b705cfSriastradh			xBack += widthBack;
24003b705cfSriastradh			widthBack = -widthBack;
24103b705cfSriastradh		}
24203b705cfSriastradh		yBack = y - FONTASCENT(gc->font);
24303b705cfSriastradh		heightBack = FONTASCENT(gc->font) + FONTDESCENT(gc->font);
24403b705cfSriastradh		fbSolidBoxClipped(drawable, gc,
24503b705cfSriastradh				  xBack, yBack,
24603b705cfSriastradh				  xBack + widthBack,
24703b705cfSriastradh				  yBack + heightBack);
24803b705cfSriastradh		opaque = FALSE;
24903b705cfSriastradh	}
25003b705cfSriastradh
25103b705cfSriastradh	ppci = ppciInit;
25203b705cfSriastradh	while (nglyph--) {
25303b705cfSriastradh		pci = *ppci++;
25403b705cfSriastradh		pglyph = FONTGLYPHBITS(glyphs, pci);
25503b705cfSriastradh		gWidth = GLYPHWIDTHPIXELS(pci);
25603b705cfSriastradh		gHeight = GLYPHHEIGHTPIXELS(pci);
25703b705cfSriastradh		if (gWidth && gHeight) {
25803b705cfSriastradh			gx = x + pci->metrics.leftSideBearing;
25903b705cfSriastradh			gy = y - pci->metrics.ascent;
26003b705cfSriastradh			if (raster && gWidth <= sizeof(FbStip) * 8 &&
26103b705cfSriastradh			    fbGlyphIn(gc, gx, gy, gWidth, gHeight)) {
26203b705cfSriastradh				fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff,
26303b705cfSriastradh					      dstYoff);
26403b705cfSriastradh				raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
26503b705cfSriastradh				       (FbStip *) pglyph, pgc->fg, gx + dstXoff, gHeight);
26603b705cfSriastradh			} else {
26703b705cfSriastradh				gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip);
26803b705cfSriastradh				fbPutXYImage(drawable, gc,
26903b705cfSriastradh					     pgc->fg, pgc->bg, pgc->pm,
27003b705cfSriastradh					     GXcopy, opaque,
27103b705cfSriastradh					     gx, gy, gWidth, gHeight,
27203b705cfSriastradh					     (FbStip *) pglyph, gStride, 0);
27303b705cfSriastradh			}
27403b705cfSriastradh		}
27503b705cfSriastradh		x += pci->metrics.characterWidth;
27603b705cfSriastradh	}
27703b705cfSriastradh}
278