1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rre.c
3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Routines to implement Rise-and-Run-length Encoding (RRE).  This
5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * code is based on krw's original javatel rfbserver.
6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  All Rights Reserved.
12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This is free software; you can redistribute it and/or modify
14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  it under the terms of the GNU General Public License as published by
15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  the Free Software Foundation; either version 2 of the License, or
16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  (at your option) any later version.
17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This software is distributed in the hope that it will be useful,
19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  GNU General Public License for more details.
22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  You should have received a copy of the GNU General Public License
24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  along with this software; if not, write to the Free Software
25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  USA.
27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfb.h>
30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * cl->beforeEncBuf contains pixel data in the client's format.
33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * cl->afterEncBuf contains the RRE encoded version.  If the RRE encoded version is
34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * larger than the raw data or if it exceeds cl->afterEncBufSize then
35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * raw encoding is used instead.
36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int subrectEncode8(rfbClientPtr cl, uint8_t *data, int w, int h);
39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int subrectEncode16(rfbClientPtr cl, uint16_t *data, int w, int h);
40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int subrectEncode32(rfbClientPtr cl, uint32_t *data, int w, int h);
41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic uint32_t getBgColour(char *data, int size, int bpp);
42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding.
46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendRectEncodingRRE(rfbClientPtr cl,
50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int x,
51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int y,
52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int w,
53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int h)
54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbRREHeader hdr;
57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int nSubrects;
58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int i;
59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                   + (x * (cl->scaledScreen->bitsPerPixel / 8)));
61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                      * (cl->format.bitsPerPixel / 8));
64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->beforeEncBufSize < maxRawSize) {
66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->beforeEncBufSize = maxRawSize;
67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->beforeEncBuf == NULL)
68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        else
70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->afterEncBufSize < maxRawSize) {
74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->afterEncBufSize = maxRawSize;
75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->afterEncBuf == NULL)
76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        else
78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    (*cl->translateFn)(cl->translateLookupTable,
82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		       &(cl->screen->serverFormat),
83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       &cl->format, fbptr, cl->beforeEncBuf,
84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       cl->scaledScreen->paddedWidthInBytes, w, h);
85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    switch (cl->format.bitsPerPixel) {
87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case 8:
88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        nSubrects = subrectEncode8(cl, (uint8_t *)cl->beforeEncBuf, w, h);
89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case 16:
91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        nSubrects = subrectEncode16(cl, (uint16_t *)cl->beforeEncBuf, w, h);
92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case 32:
94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        nSubrects = subrectEncode32(cl, (uint32_t *)cl->beforeEncBuf, w, h);
95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    default:
97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (nSubrects < 0) {
102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* RRE encoding was too large, use raw */
104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return rfbSendRectEncodingRaw(cl, x, y, w, h);
106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordEncodingSent(cl, rfbEncodingRRE,
109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                              sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + cl->afterEncBufLen,
110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                              sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        > UPDATE_BUF_SIZE)
114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (!rfbSendUpdateBuf(cl))
116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.x = Swap16IfLE(x);
120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.y = Swap16IfLE(y);
121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.w = Swap16IfLE(w);
122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.h = Swap16IfLE(h);
123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.encoding = Swap32IfLE(rfbEncodingRRE);
124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           sz_rfbFramebufferUpdateRectHeader);
127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    hdr.nSubrects = Swap32IfLE(nSubrects);
130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbRREHeader;
133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for (i = 0; i < cl->afterEncBufLen;) {
135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (i + bytesToCopy > cl->afterEncBufLen) {
139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            bytesToCopy = cl->afterEncBufLen - i;
140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);
143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->ublen += bytesToCopy;
145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        i += bytesToCopy;
146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->ublen == UPDATE_BUF_SIZE) {
148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (!rfbSendUpdateBuf(cl))
149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                return FALSE;
150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * subrectEncode() encodes the given multicoloured rectangle as a background
160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * colour overwritten by single-coloured rectangles.  It returns the number
161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * of subrectangles in the encoded buffer, or -1 if subrect encoding won't
162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * fit in the buffer.  It puts the encoded rectangles in cl->afterEncBuf.  The
163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * single-colour rectangle partition is not optimal, but does find the biggest
164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * horizontal or vertical rectangle top-left anchored to each consecutive
165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * coordinate position.
166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * <subrect> is [<colour><x><y><w><h>].
169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define DEFINE_SUBRECT_ENCODE(bpp)                                            \
172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int                                                                    \
173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat subrectEncode##bpp(rfbClientPtr client, uint##bpp##_t *data, int w, int h) { \
174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint##bpp##_t cl;                                                         \
175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbRectangle subrect;                                                     \
176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int x,y;                                                                  \
177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int i,j;                                                                  \
178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int hx=0,hy,vx=0,vy;                                                      \
179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int hyflag;                                                               \
180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint##bpp##_t *seg;                                                       \
181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint##bpp##_t *line;                                                      \
182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int hw,hh,vw,vh;                                                          \
183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int thex,they,thew,theh;                                                  \
184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int numsubs = 0;                                                          \
185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int newLen;                                                               \
186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp);       \
187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    *((uint##bpp##_t*)client->afterEncBuf) = bg;                                      \
189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    client->afterEncBufLen = (bpp/8);                                                 \
191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for (y=0; y<h; y++) {                                                     \
193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      line = data+(y*w);                                                      \
194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      for (x=0; x<w; x++) {                                                   \
195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (line[x] != bg) {                                                  \
196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          cl = line[x];                                                       \
197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          hy = y-1;                                                           \
198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          hyflag = 1;                                                         \
199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          for (j=y; j<h; j++) {                                               \
200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            seg = data+(j*w);                                                 \
201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (seg[x] != cl) {break;}                                        \
202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            i = x;                                                            \
203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            while ((seg[i] == cl) && (i < w)) i += 1;                         \
204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            i -= 1;                                                           \
205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (j == y) vx = hx = i;                                          \
206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (i < vx) vx = i;                                               \
207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;}      \
208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          }                                                                   \
209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          vy = j-1;                                                           \
210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          /*  We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy)  \
212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           *  We'll choose the bigger of the two.                             \
213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           */                                                                 \
214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          hw = hx-x+1;                                                        \
215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          hh = hy-y+1;                                                        \
216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          vw = vx-x+1;                                                        \
217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          vh = vy-y+1;                                                        \
218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          thex = x;                                                           \
220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          they = y;                                                           \
221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          if ((hw*hh) > (vw*vh)) {                                            \
223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            thew = hw;                                                        \
224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            theh = hh;                                                        \
225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          } else {                                                            \
226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            thew = vw;                                                        \
227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            theh = vh;                                                        \
228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          }                                                                   \
229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          subrect.x = Swap16IfLE(thex);                                       \
231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          subrect.y = Swap16IfLE(they);                                       \
232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          subrect.w = Swap16IfLE(thew);                                       \
233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          subrect.h = Swap16IfLE(theh);                                       \
234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          newLen = client->afterEncBufLen + (bpp/8) + sz_rfbRectangle;                \
236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          if ((newLen > (w * h * (bpp/8))) || (newLen > client->afterEncBufSize))     \
237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return -1;                                                        \
238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          numsubs += 1;                                                       \
240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          *((uint##bpp##_t*)(client->afterEncBuf + client->afterEncBufLen)) = cl;             \
241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          client->afterEncBufLen += (bpp/8);                                          \
242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          memcpy(&client->afterEncBuf[client->afterEncBufLen],&subrect,sz_rfbRectangle);      \
243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          client->afterEncBufLen += sz_rfbRectangle;                                  \
244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          /*                                                                  \
246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           * Now mark the subrect as done.                                    \
247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           */                                                                 \
248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          for (j=they; j < (they+theh); j++) {                                \
249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            for (i=thex; i < (thex+thew); i++) {                              \
250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              data[j*w+i] = bg;                                               \
251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }                                                                 \
252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          }                                                                   \
253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }                                                                     \
254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }                                                                       \
255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }                                                                         \
256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                                                                              \
257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return numsubs;                                                           \
258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatDEFINE_SUBRECT_ENCODE(8)
261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatDEFINE_SUBRECT_ENCODE(16)
262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatDEFINE_SUBRECT_ENCODE(32)
263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * getBgColour() gets the most prevalent colour in a byte array.
267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic uint32_t
269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatgetBgColour(char *data, int size, int bpp)
270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define NUMCLRS 256
273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  static int counts[NUMCLRS];
275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int i,j,k;
276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int maxcount = 0;
278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  uint8_t maxclr = 0;
279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (bpp != 8) {
281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (bpp == 16) {
282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return ((uint16_t *)data)[0];
283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if (bpp == 32) {
284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return ((uint32_t *)data)[0];
285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else {
286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbLog("getBgColour: bpp %d?\n",bpp);
287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return 0;
288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  for (i=0; i<NUMCLRS; i++) {
292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    counts[i] = 0;
293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  for (j=0; j<size; j++) {
296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    k = (int)(((uint8_t *)data)[j]);
297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (k >= NUMCLRS) {
298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbErr("getBgColour: unusual colour = %d\n", k);
299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return 0;
300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    counts[k] += 1;
302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (counts[k] > maxcount) {
303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      maxcount = counts[k];
304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      maxclr = ((uint8_t *)data)[j];
305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return maxclr;
309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
310