1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 1998 Keith Packard
3428d7b3dSmrg * Copyright © 2012 Intel Corporation
4428d7b3dSmrg *
5428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
6428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that
7428d7b3dSmrg * the above copyright notice appear in all copies and that both that
8428d7b3dSmrg * copyright notice and this permission notice appear in supporting
9428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in
10428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without
11428d7b3dSmrg * specific, written prior permission.  Keith Packard makes no
12428d7b3dSmrg * representations about the suitability of this software for any purpose.  It
13428d7b3dSmrg * is provided "as is" without express or implied warranty.
14428d7b3dSmrg *
15428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE.
22428d7b3dSmrg */
23428d7b3dSmrg
24428d7b3dSmrg#include "fb.h"
25428d7b3dSmrg#include "fbclip.h"
26428d7b3dSmrg
27428d7b3dSmrgstatic void
28428d7b3dSmrgfbPushPattern(DrawablePtr drawable, GCPtr gc,
29428d7b3dSmrg              FbStip *src, FbStride srcStride, int srcX,
30428d7b3dSmrg	      int x, int y, int width, int height)
31428d7b3dSmrg{
32428d7b3dSmrg	FbStip *s, bitsMask, bitsMask0, bits;
33428d7b3dSmrg	int xspan;
34428d7b3dSmrg	int w;
35428d7b3dSmrg	int lenspan;
36428d7b3dSmrg
37428d7b3dSmrg	src += srcX >> FB_STIP_SHIFT;
38428d7b3dSmrg	srcX &= FB_STIP_MASK;
39428d7b3dSmrg
40428d7b3dSmrg	bitsMask0 = FbStipMask(srcX, 1);
41428d7b3dSmrg
42428d7b3dSmrg	while (height--) {
43428d7b3dSmrg		bitsMask = bitsMask0;
44428d7b3dSmrg		w = width;
45428d7b3dSmrg		s = src;
46428d7b3dSmrg		src += srcStride;
47428d7b3dSmrg		bits = READ(s++);
48428d7b3dSmrg		xspan = x;
49428d7b3dSmrg		while (w) {
50428d7b3dSmrg			if (bits & bitsMask) {
51428d7b3dSmrg				lenspan = 0;
52428d7b3dSmrg				do {
53428d7b3dSmrg					if (++lenspan == w)
54428d7b3dSmrg						break;
55428d7b3dSmrg
56428d7b3dSmrg					bitsMask = FbStipRight(bitsMask, 1);
57428d7b3dSmrg					if (!bitsMask) {
58428d7b3dSmrg						bits = READ(s++);
59428d7b3dSmrg						bitsMask = FbBitsMask(0, 1);
60428d7b3dSmrg					}
61428d7b3dSmrg				} while (bits & bitsMask);
62428d7b3dSmrg				fbFill(drawable, gc, xspan, y, lenspan, 1);
63428d7b3dSmrg				xspan += lenspan;
64428d7b3dSmrg				w -= lenspan;
65428d7b3dSmrg			} else {
66428d7b3dSmrg				do {
67428d7b3dSmrg					xspan++;
68428d7b3dSmrg					if (!--w)
69428d7b3dSmrg						break;
70428d7b3dSmrg
71428d7b3dSmrg					bitsMask = FbStipRight(bitsMask, 1);
72428d7b3dSmrg					if (!bitsMask) {
73428d7b3dSmrg						bits = READ(s++);
74428d7b3dSmrg						bitsMask = FbBitsMask(0, 1);
75428d7b3dSmrg					}
76428d7b3dSmrg				} while (!(bits & bitsMask));
77428d7b3dSmrg			}
78428d7b3dSmrg		}
79428d7b3dSmrg		y++;
80428d7b3dSmrg	}
81428d7b3dSmrg}
82428d7b3dSmrg
83428d7b3dSmrgstatic void
84428d7b3dSmrgfbPushFill(DrawablePtr drawable, GCPtr gc,
85428d7b3dSmrg           FbStip *src, FbStride srcStride, int srcX,
86428d7b3dSmrg	   int x, int y, int width, int height)
87428d7b3dSmrg{
88428d7b3dSmrg	FbGCPrivPtr pgc = fb_gc(gc);
89428d7b3dSmrg
90428d7b3dSmrg	if (gc->fillStyle == FillSolid) {
91428d7b3dSmrg		FbBits *dst;
92428d7b3dSmrg		FbStride dstStride;
93428d7b3dSmrg		int dstBpp;
94428d7b3dSmrg		int dstXoff, dstYoff;
95428d7b3dSmrg		int dstX;
96428d7b3dSmrg		int dstWidth;
97428d7b3dSmrg
98428d7b3dSmrg		fbGetDrawable(drawable, dst,
99428d7b3dSmrg			      dstStride, dstBpp, dstXoff, dstYoff);
100428d7b3dSmrg		dst = dst + (y + dstYoff) * dstStride;
101428d7b3dSmrg		dstX = (x + dstXoff) * dstBpp;
102428d7b3dSmrg		dstWidth = width * dstBpp;
103428d7b3dSmrg		if (dstBpp == 1) {
104428d7b3dSmrg			fbBltStip(src, srcStride, srcX,
105428d7b3dSmrg				  (FbStip *)dst, dstStride, dstX,
106428d7b3dSmrg				  dstWidth, height,
107428d7b3dSmrg				  FbStipple1Rop(gc->alu, gc->fgPixel), pgc->pm, dstBpp);
108428d7b3dSmrg		} else {
109428d7b3dSmrg			fbBltOne(src, srcStride, srcX,
110428d7b3dSmrg				 dst, dstStride, dstX, dstBpp,
111428d7b3dSmrg				 dstWidth, height,
112428d7b3dSmrg				 pgc->and, pgc->xor,
113428d7b3dSmrg				 fbAnd(GXnoop, (FbBits) 0, FB_ALLONES),
114428d7b3dSmrg				 fbXor(GXnoop, (FbBits) 0, FB_ALLONES));
115428d7b3dSmrg		}
116428d7b3dSmrg	} else
117428d7b3dSmrg		fbPushPattern(drawable, gc, src, srcStride, srcX,
118428d7b3dSmrg			      x, y, width, height);
119428d7b3dSmrg}
120428d7b3dSmrg
121428d7b3dSmrgstruct fbPushImage {
122428d7b3dSmrg	FbStip *src;
123428d7b3dSmrg	FbStride stride;
124428d7b3dSmrg	int x0, y0;
125428d7b3dSmrg};
126428d7b3dSmrg
127428d7b3dSmrginline static void
128428d7b3dSmrg_fbPushImage(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
129428d7b3dSmrg{
130428d7b3dSmrg	struct fbPushImage *data = _data;
131428d7b3dSmrg
132428d7b3dSmrg	fbPushFill(drawable, gc,
133428d7b3dSmrg		   data->src + (b->y1 - data->y0) * data->stride, data->stride,
134428d7b3dSmrg		   b->x1 - data->x0,
135428d7b3dSmrg		   b->x1, b->y1,
136428d7b3dSmrg		   b->x2 - b->x1, b->y2 - b->y1);
137428d7b3dSmrg}
138428d7b3dSmrg
139428d7b3dSmrgvoid
140428d7b3dSmrgfbPushImage(DrawablePtr drawable, GCPtr gc,
141428d7b3dSmrg            FbStip *src, FbStride stride, int dx,
142428d7b3dSmrg	    int x, int y, int width, int height)
143428d7b3dSmrg{
144428d7b3dSmrg	struct fbPushImage data;
145428d7b3dSmrg	BoxRec box;
146428d7b3dSmrg
147428d7b3dSmrg	DBG(("%s (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, width, height));
148428d7b3dSmrg
149428d7b3dSmrg	data.src = src;
150428d7b3dSmrg	data.stride = stride;
151428d7b3dSmrg	data.y0 = y;
152428d7b3dSmrg	data.x0 = x - dx;
153428d7b3dSmrg
154428d7b3dSmrg	box.x1 = x;
155428d7b3dSmrg	box.y1 = y;
156428d7b3dSmrg	box.x2 = x + width;
157428d7b3dSmrg	box.y2 = y + height;
158428d7b3dSmrg	fbDrawableRun(drawable, gc, &box, _fbPushImage, &data);
159428d7b3dSmrg}
160428d7b3dSmrg
161428d7b3dSmrgvoid
162428d7b3dSmrgfbPushPixels(GCPtr gc, PixmapPtr bitmap, DrawablePtr drawable,
163428d7b3dSmrg	     int dx, int dy, int xOrg, int yOrg)
164428d7b3dSmrg{
165428d7b3dSmrg	FbStip *stip;
166428d7b3dSmrg	FbStride stipStride;
167428d7b3dSmrg	int stipBpp;
168428d7b3dSmrg	_X_UNUSED int stipXoff, stipYoff;
169428d7b3dSmrg
170428d7b3dSmrg	DBG(("%s bitmap=%x%d\n", __FUNCTION__,
171428d7b3dSmrg	     bitmap->drawable.width, bitmap->drawable.height));
172428d7b3dSmrg
173428d7b3dSmrg	fbGetStipDrawable(&bitmap->drawable, stip,
174428d7b3dSmrg			  stipStride, stipBpp, stipXoff, stipYoff);
175428d7b3dSmrg
176428d7b3dSmrg	fbPushImage(drawable, gc, stip, stipStride, 0, xOrg, yOrg, dx, dy);
177428d7b3dSmrg}
178