1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 /*
24 * This code is based on original Tony Tough source code
25 *
26 * Copyright (c) 1997-2003 Nayma Software
27 */
28
29 #include "tony/gfxengine.h"
30 #include "tony/mpal/mpalutils.h"
31 #include "tony/tony.h"
32
33 namespace Tony {
34
35 /****************************************************************************\
36 * RMGfxTask Methods
37 \****************************************************************************/
38
RMGfxTask()39 RMGfxTask::RMGfxTask() {
40 _nPrior = 0;
41 _nInList = 0;
42 }
43
priority()44 int RMGfxTask::priority() {
45 return _nPrior;
46 }
47
removeThis(CORO_PARAM,bool & result)48 void RMGfxTask::removeThis(CORO_PARAM, bool &result) {
49 result = true;
50 }
51
52 /**
53 * Registration
54 */
Register()55 void RMGfxTask::Register() {
56 _nInList++;
57 }
58
unregister()59 void RMGfxTask::unregister() {
60 _nInList--;
61 assert(_nInList >= 0);
62 }
63
64 /****************************************************************************\
65 * RMGfxTaskSetPrior Methods
66 \****************************************************************************/
67
setPriority(int nPrior)68 void RMGfxTaskSetPrior::setPriority(int nPrior) {
69 _nPrior = nPrior;
70 }
71
72 /****************************************************************************\
73 * RMGfxBuffer Methods
74 \****************************************************************************/
75
RMGfxBuffer()76 RMGfxBuffer::RMGfxBuffer() {
77 _dimx = _dimy = 0;
78 _origBuf = _buf = NULL;
79 }
80
~RMGfxBuffer()81 RMGfxBuffer::~RMGfxBuffer() {
82 destroy();
83 }
84
create(int dimx,int dimy,int nBpp)85 void RMGfxBuffer::create(int dimx, int dimy, int nBpp) {
86 // Destroy the buffer it is already exists
87 if (_buf != NULL)
88 destroy();
89
90 // Copy the parameters in the private members
91 _dimx = dimx;
92 _dimy = dimy;
93
94 // Allocate a buffer
95 _origBuf = _buf = new byte[_dimx * _dimy * nBpp / 8];
96 assert(_buf != NULL);
97 Common::fill(_origBuf, _origBuf + _dimx * _dimy * nBpp / 8, 0);
98 }
99
destroy()100 void RMGfxBuffer::destroy() {
101 if (_origBuf != NULL && _origBuf == _buf) {
102 delete[] _origBuf;
103 _origBuf = _buf = NULL;
104 }
105 }
106
offsetY(int nLines,int nBpp)107 void RMGfxBuffer::offsetY(int nLines, int nBpp) {
108 _buf += nLines * getDimx() * nBpp / 8;
109 }
110
operator byte*()111 RMGfxBuffer::operator byte *() {
112 return _buf;
113 }
114
operator void*()115 RMGfxBuffer::operator void *() {
116 return (void *)_buf;
117 }
118
RMGfxBuffer(int dimx,int dimy,int nBpp)119 RMGfxBuffer::RMGfxBuffer(int dimx, int dimy, int nBpp) {
120 _origBuf = _buf = NULL;
121 create(dimx, dimy, nBpp);
122 }
123
getDimx()124 int RMGfxBuffer::getDimx() {
125 return _dimx;
126 }
127
getDimy()128 int RMGfxBuffer::getDimy() {
129 return _dimy;
130 }
131
132 /****************************************************************************\
133 * RMGfxSourceBuffer Methods
134 \****************************************************************************/
135
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)136 int RMGfxSourceBuffer::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
137 create(dimx, dimy, getBpp());
138 memcpy(_buf, buf, dimx * dimy * getBpp() / 8);
139
140 // Invokes the method for preparing the surface (inherited)
141 prepareImage();
142
143 return dimx * dimy * getBpp() / 8;
144 }
145
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)146 void RMGfxSourceBuffer::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
147 create(dimx, dimy, getBpp());
148 ds.read(_buf, dimx * dimy * getBpp() / 8);
149
150 // Invokes the method for preparing the surface (inherited)
151 prepareImage();
152 }
153
~RMGfxSourceBuffer()154 RMGfxSourceBuffer::~RMGfxSourceBuffer() {
155 }
156
prepareImage()157 void RMGfxSourceBuffer::prepareImage() {
158 // Do nothing. Can be overloaded if necessary
159 }
160
clip2D(int & x1,int & y1,int & u,int & v,int & width,int & height,bool bUseSrc,RMGfxTargetBuffer * buf)161 bool RMGfxSourceBuffer::clip2D(int &x1, int &y1, int &u, int &v, int &width, int &height, bool bUseSrc, RMGfxTargetBuffer *buf) {
162 int destw, desth;
163
164 destw = buf->getDimx();
165 desth = buf->getDimy();
166
167 if (!bUseSrc) {
168 u = v = 0;
169 width = _dimx;
170 height = _dimy;
171 }
172
173 if (x1 > destw - 1)
174 return false;
175
176 if (y1 > desth - 1)
177 return false;
178
179 if (x1 < 0) {
180 width += x1;
181 if (width < 0)
182 return false;
183 u -= x1;
184 x1 = 0;
185 }
186
187 if (y1 < 0) {
188 height += y1;
189 if (height < 0)
190 return false;
191 v -= y1;
192 y1 = 0;
193 }
194
195 if (x1 + width - 1 > destw - 1)
196 width = destw - x1;
197
198 if (y1 + height - 1 > desth - 1)
199 height = desth - y1;
200
201 return (width > 1 && height > 1);
202 }
203
204 /**
205 * Initializes a surface by resource Id
206 *
207 * @param resID Resource ID
208 * @param dimx Buffer X dimension
209 * @param dimy Buffer Y dimension
210 */
init(uint32 resID,int dimx,int dimy,bool bLoadPalette)211 int RMGfxSourceBuffer::init(uint32 resID, int dimx, int dimy, bool bLoadPalette) {
212 return init(RMRes(resID), dimx, dimy, bLoadPalette);
213 }
214
offsetY(int nLines)215 void RMGfxSourceBuffer::offsetY(int nLines) {
216 RMGfxBuffer::offsetY(nLines, getBpp());
217 }
218
219 /****************************************************************************\
220 * RMGfxWoodyBuffer Methods
221 \****************************************************************************/
222
~RMGfxWoodyBuffer()223 RMGfxWoodyBuffer::~RMGfxWoodyBuffer() {
224 }
225
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)226 void RMGfxWoodyBuffer::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
227 CORO_BEGIN_CONTEXT;
228 CORO_END_CONTEXT(_ctx);
229
230 CORO_BEGIN_CODE(_ctx);
231
232 // Draw the OT list
233 CORO_INVOKE_0(drawOT);
234
235 // Draw itself into the target buffer
236 CORO_INVOKE_2(RMGfxSourceBuffer16::draw, bigBuf, prim);
237
238 CORO_END_CODE;
239 }
240
RMGfxWoodyBuffer()241 RMGfxWoodyBuffer::RMGfxWoodyBuffer() {
242 }
243
RMGfxWoodyBuffer(int dimx,int dimy)244 RMGfxWoodyBuffer::RMGfxWoodyBuffer(int dimx, int dimy)
245 : RMGfxBuffer(dimx, dimy, 16) {
246 }
247
248 /****************************************************************************\
249 * RMGfxTargetBuffer Methods
250 \****************************************************************************/
251
RMGfxTargetBuffer()252 RMGfxTargetBuffer::RMGfxTargetBuffer() {
253 _otlist = NULL;
254 _otSize = 0;
255 _trackDirtyRects = false;
256 }
257
~RMGfxTargetBuffer()258 RMGfxTargetBuffer::~RMGfxTargetBuffer() {
259 clearOT();
260 }
261
clearOT()262 void RMGfxTargetBuffer::clearOT() {
263 OTList *cur, *n;
264
265 cur = _otlist;
266
267 while (cur != NULL) {
268 cur->_prim->_task->unregister();
269 delete cur->_prim;
270 n = cur->_next;
271 delete cur;
272 cur = n;
273 }
274
275 _otlist = NULL;
276 }
277
drawOT(CORO_PARAM)278 void RMGfxTargetBuffer::drawOT(CORO_PARAM) {
279 CORO_BEGIN_CONTEXT;
280 OTList *cur;
281 OTList *prev;
282 OTList *next;
283 RMGfxPrimitive *myprim;
284 bool result;
285 CORO_END_CONTEXT(_ctx);
286
287 CORO_BEGIN_CODE(_ctx);
288
289 _ctx->prev = NULL;
290 _ctx->cur = _otlist;
291
292 while (_ctx->cur != NULL) {
293 // Call the task Draw method, passing it a copy of the original
294 _ctx->myprim = _ctx->cur->_prim->duplicate();
295 CORO_INVOKE_2(_ctx->cur->_prim->_task->draw, *this, _ctx->myprim);
296 delete _ctx->myprim;
297
298 // Check if it's time to remove the task from the OT list
299 CORO_INVOKE_1(_ctx->cur->_prim->_task->removeThis, _ctx->result);
300 if (_ctx->result) {
301 // De-register the task
302 _ctx->cur->_prim->_task->unregister();
303
304 // Delete task, freeing the memory
305 delete _ctx->cur->_prim;
306 _ctx->next = _ctx->cur->_next;
307 delete _ctx->cur;
308
309 // If it was the first item, update the list head
310 if (_ctx->prev == NULL)
311 _otlist = _ctx->next;
312 // Otherwise update the next pinter of the previous item
313 else
314 _ctx->prev->_next = _ctx->next;
315
316 _ctx->cur = _ctx->next;
317 } else {
318 // Update the pointer to the previous item, and the current to the next
319 _ctx->prev = _ctx->cur;
320 _ctx->cur = _ctx->cur->_next;
321 }
322 }
323
324 CORO_END_CODE;
325 }
326
addPrim(RMGfxPrimitive * prim)327 void RMGfxTargetBuffer::addPrim(RMGfxPrimitive *prim) {
328 int nPrior;
329 OTList *cur, *n;
330
331 // Warn of the OT listing
332 prim->_task->Register();
333
334 // Check the priority
335 nPrior = prim->_task->priority();
336 n = new OTList(prim);
337
338 // Empty list
339 if (_otlist == NULL) {
340 _otlist = n;
341 _otlist->_next = NULL;
342 }
343 // Inclusion in the head
344 else if (nPrior < _otlist->_prim->_task->priority()) {
345 n->_next = _otlist;
346 _otlist = n;
347 } else {
348 cur = _otlist;
349 while (cur->_next != NULL && nPrior > cur->_next->_prim->_task->priority())
350 cur = cur->_next;
351
352 n->_next = cur->_next;
353 cur->_next = n;
354 }
355 }
356
addDirtyRect(const Common::Rect & r)357 void RMGfxTargetBuffer::addDirtyRect(const Common::Rect &r) {
358 assert(r.isValidRect());
359 if (_trackDirtyRects && r.width() > 0 && r.height() > 0)
360 _currentDirtyRects.push_back(r);
361 }
362
getDirtyRects()363 Common::List<Common::Rect> &RMGfxTargetBuffer::getDirtyRects() {
364 // Copy rects from both the current and previous frame into the output dirty rects list
365 Common::List<Common::Rect>::iterator i;
366 _dirtyRects.clear();
367 for (i = _previousDirtyRects.begin(); i != _previousDirtyRects.end(); ++i)
368 _dirtyRects.push_back(*i);
369 for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i)
370 _dirtyRects.push_back(*i);
371
372 mergeDirtyRects();
373 return _dirtyRects;
374 }
375
376 /**
377 * Move the set of dirty rects from the finished current frame into the previous frame list.
378 */
clearDirtyRects()379 void RMGfxTargetBuffer::clearDirtyRects() {
380 Common::List<Common::Rect>::iterator i;
381 _previousDirtyRects.clear();
382 for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i)
383 _previousDirtyRects.push_back(*i);
384
385 _currentDirtyRects.clear();
386 }
387
388 /**
389 * Merges any clipping rectangles that overlap to try and reduce
390 * the total number of clip rectangles.
391 */
mergeDirtyRects()392 void RMGfxTargetBuffer::mergeDirtyRects() {
393 if (_dirtyRects.size() <= 1)
394 return;
395
396 Common::List<Common::Rect>::iterator rOuter, rInner;
397
398 for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
399 rInner = rOuter;
400 while (++rInner != _dirtyRects.end()) {
401
402 if ((*rOuter).intersects(*rInner)) {
403 // these two rectangles overlap or
404 // are next to each other - merge them
405
406 (*rOuter).extend(*rInner);
407
408 // remove the inner rect from the list
409 _dirtyRects.erase(rInner);
410
411 // move back to beginning of list
412 rInner = rOuter;
413 }
414 }
415 }
416 }
417
418 uint16 *RMGfxTargetBuffer::_precalcTable = NULL;
419
420 /**
421 * Set up the black & white precalculated mapping table. This is only
422 * called if the user selects the black & white option.
423 */
createBWPrecalcTable()424 void RMGfxTargetBuffer::createBWPrecalcTable() {
425 _precalcTable = new uint16[0x10000];
426
427 for (int i = 0; i < 0x10000; i++) {
428 int r = (i >> 11) & 0x1F;
429 int g = (i >> 6) & 0x1F;
430 int b = i & 0x1F;
431
432 int min = MIN(r, MIN(g, b));
433 int max = MAX(r, MAX(g, b));
434
435 min = (min + max) / 2;
436
437 r = CLIP(min + 8 - 8, 0, 0x1f);
438 g = CLIP(min + 5 - 8, 0, 0x1f);
439 b = CLIP(min + 0 - 8, 0, 0x1f);
440
441 _precalcTable[i] = (r << 11) | (g << 6) | b;
442 }
443 }
444
445 /**
446 * Frees the black & white precalculated mapping table.
447 */
freeBWPrecalcTable()448 void RMGfxTargetBuffer::freeBWPrecalcTable() {
449 delete[] _precalcTable;
450 _precalcTable = NULL;
451 }
452
operator byte*()453 RMGfxTargetBuffer::operator byte *() {
454 return _buf;
455 }
456
operator void*()457 RMGfxTargetBuffer::operator void *() {
458 return (void *)_buf;
459 }
460
operator uint16*()461 RMGfxTargetBuffer::operator uint16 *() {
462 // FIXME: This may not be endian safe
463 return (uint16 *)_buf;
464 }
465
466 /**
467 * Offseting buffer
468 */
offsetY(int nLines)469 void RMGfxTargetBuffer::offsetY(int nLines) {
470 RMGfxBuffer::offsetY(nLines, 16);
471 }
472
setTrackDirtyRects(bool v)473 void RMGfxTargetBuffer::setTrackDirtyRects(bool v) {
474 _trackDirtyRects = v;
475 }
476
getTrackDirtyRects() const477 bool RMGfxTargetBuffer::getTrackDirtyRects() const {
478 return _trackDirtyRects;
479 }
480
481 /****************************************************************************\
482 * RMGfxSourceBufferPal Methods
483 \****************************************************************************/
484
~RMGfxSourceBufferPal()485 RMGfxSourceBufferPal::~RMGfxSourceBufferPal() {
486 }
487
loadPaletteWA(const byte * buf,bool bSwapped)488 int RMGfxSourceBufferPal::loadPaletteWA(const byte *buf, bool bSwapped) {
489 if (bSwapped) {
490 for (int i = 0; i < (1 << getBpp()); i++) {
491 _pal[i * 3 + 0] = buf[i * 3 + 2];
492 _pal[i * 3 + 1] = buf[i * 3 + 1];
493 _pal[i * 3 + 2] = buf[i * 3 + 0];
494 }
495 } else {
496 memcpy(_pal, buf, (1 << getBpp()) * 3);
497 }
498
499 preparePalette();
500
501 return (1 << getBpp()) * 3;
502 }
503
loadPalette(const byte * buf)504 int RMGfxSourceBufferPal::loadPalette(const byte *buf) {
505 for (int i = 0; i < 256; i++)
506 memcpy(_pal + i * 3, buf + i * 4, 3);
507
508 preparePalette();
509
510 return (1 << getBpp()) * 4;
511 }
512
preparePalette()513 void RMGfxSourceBufferPal::preparePalette() {
514 for (int i = 0; i < 256; i++) {
515 // we convert 555 to 565 here.
516 _palFinal[i] = (((int)_pal[i * 3 + 0] >> 3) << 11) |
517 (((int)_pal[i * 3 + 1] >> 3) << 6) |
518 (((int)_pal[i * 3 + 2] >> 3) << 0);
519 }
520 }
521
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)522 int RMGfxSourceBufferPal::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
523 // Load the RAW image
524 int read = RMGfxSourceBuffer::init(buf, dimx, dimy);
525
526 // Load the palette if necessary
527 if (bLoadPalette)
528 read += loadPaletteWA(&buf[read]);
529
530 return read;
531 }
532
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)533 void RMGfxSourceBufferPal::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
534 // Load the RAW image
535 RMGfxSourceBuffer::init(ds, dimx, dimy);
536
537 // Load the palette if necessary
538 if (bLoadPalette) {
539 byte *suxpal = new byte[256 * 3];
540 ds.read(suxpal, 256 * 3);
541 loadPaletteWA(suxpal);
542 delete[] suxpal;
543 }
544 }
545
loadPalette(uint32 resID)546 int RMGfxSourceBufferPal::loadPalette(uint32 resID) {
547 return loadPalette(RMRes(resID));
548 }
549
loadPaletteWA(uint32 resID,bool bSwapped)550 int RMGfxSourceBufferPal::loadPaletteWA(uint32 resID, bool bSwapped) {
551 return loadPaletteWA(RMRes(resID), bSwapped);
552 }
553
554 /****************************************************************************\
555 * RMGfxSourceBuffer4 Methods
556 \****************************************************************************/
557
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)558 void RMGfxSourceBuffer4::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
559 }
560
RMGfxSourceBuffer4(int dimx,int dimy)561 RMGfxSourceBuffer4::RMGfxSourceBuffer4(int dimx, int dimy)
562 : RMGfxBuffer(dimx, dimy, 4) {
563 setPriority(0);
564 }
565
566 /**
567 * Returns the number of bits per pixel of the surface
568 *
569 * @returns Bit per pixel
570 */
getBpp()571 int RMGfxSourceBuffer4::getBpp() {
572 return 4;
573 }
574
create(int dimx,int dimy)575 void RMGfxSourceBuffer4::create(int dimx, int dimy) {
576 RMGfxBuffer::create(dimx, dimy, 4);
577 }
578
579 /****************************************************************************\
580 * RMGfxSourceBuffer8 Methods
581 \****************************************************************************/
582
~RMGfxSourceBuffer8()583 RMGfxSourceBuffer8::~RMGfxSourceBuffer8() {
584 }
585
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)586 void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
587 int width = 0, height = 0, u = 0, v = 0;
588 int bufx = bigBuf.getDimx();
589 uint16 *buf = bigBuf;
590 byte *raw = _buf;
591
592 // Destination buffer
593 RMRect dst;
594 if (prim->haveDst())
595 dst = prim->getDst();
596
597 // Clipping
598 if (prim->haveSrc()) {
599 u = prim->getSrc()._x1;
600 v = prim->getSrc()._y1;
601
602 width = prim->getSrc().width();
603 height = prim->getSrc().height();
604 }
605
606 if (!clip2D(dst._x1, dst._y1, u, v, width, height, prim->haveSrc(), &bigBuf))
607 return;
608
609 // Starting offset into the buffer
610 buf += dst._y1 * bufx + dst._x1;
611
612 // Normal step
613 if (_bTrasp0) {
614 for (int y = 0; y < height; y++) {
615 raw = _buf + (y + v) * _dimx + u;
616
617 for (int x = 0; x < width; x++) {
618 if (*raw)
619 *buf = _palFinal[*raw];
620 buf++;
621 raw++;
622 }
623
624 buf += bufx - width;
625 }
626 } else {
627 for (int y = 0; y < height; y++) {
628 raw = _buf + (y + v) * _dimx + u;
629
630 for (int x = 0; x < width; x += 2) {
631 buf[0] = _palFinal[raw[0]];
632 buf[1] = _palFinal[raw[1]];
633
634 buf += 2;
635 raw += 2;
636 }
637
638 buf += bufx - width;
639 }
640 }
641
642 // Specify the drawn area
643 bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));
644 }
645
RMGfxSourceBuffer8(int dimx,int dimy)646 RMGfxSourceBuffer8::RMGfxSourceBuffer8(int dimx, int dimy)
647 : RMGfxBuffer(dimx, dimy, 8) {
648 setPriority(0);
649 _bTrasp0 = false;
650 }
651
RMGfxSourceBuffer8(bool bTrasp0)652 RMGfxSourceBuffer8::RMGfxSourceBuffer8(bool bTrasp0) {
653 _bTrasp0 = bTrasp0;
654 }
655
656 /**
657 * Returns the number of bits per pixel of the surface
658 *
659 * @returns Bit per pixel
660 */
getBpp()661 int RMGfxSourceBuffer8::getBpp() {
662 return 8;
663 }
664
create(int dimx,int dimy)665 void RMGfxSourceBuffer8::create(int dimx, int dimy) {
666 RMGfxBuffer::create(dimx, dimy, 8);
667 }
668
669 #define GETRED(x) (((x) >> 11) & 0x1F)
670 #define GETGREEN(x) (((x) >> 5) & 0x3F)
671 #define GETBLUE(x) ((x) & 0x1F)
672
673 /****************************************************************************\
674 * RMGfxSourceBuffer8AB Methods
675 \****************************************************************************/
676
~RMGfxSourceBuffer8AB()677 RMGfxSourceBuffer8AB::~RMGfxSourceBuffer8AB() {
678 }
679
calcTrasp(int fore,int back)680 int RMGfxSourceBuffer8AB::calcTrasp(int fore, int back) {
681 int r = (GETRED(fore) >> 2) + (GETRED(back) >> 1);
682 int g = (GETGREEN(fore) >> 2) + (GETGREEN(back) >> 1);
683 int b = (GETBLUE(fore) >> 2) + (GETBLUE(back) >> 1);
684
685 if (r > 0x1F)
686 r = 0x1F;
687
688 if (g > 0x3F)
689 g = 0x3F;
690
691 if (b > 0x1F)
692 b = 0x1F;
693
694 return (r << 11) | (g << 5) | b;
695 }
696
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)697 void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
698 int width = 0, height = 0, u = 0, v = 0;
699 int bufx = bigBuf.getDimx();
700 uint16 *buf = bigBuf;
701 byte *raw = _buf;
702
703 // Destination buffer
704 RMRect dst;
705 if (prim->haveDst())
706 dst = prim->getDst();
707
708 // Clipping
709 if (prim->haveSrc()) {
710 u = prim->getSrc()._x1;
711 v = prim->getSrc()._y1;
712
713 width = prim->getSrc().width();
714 height = prim->getSrc().height();
715 }
716
717 if (!clip2D(dst._x1, dst._y1, u, v, width, height, prim->haveSrc(), &bigBuf))
718 return;
719
720 // Starting offset into the buffer
721 buf += dst._y1 * bufx + dst._x1;
722
723 // Passaggio normale
724 if (_bTrasp0) {
725 for (int y = 0; y < height; y++) {
726 raw = _buf + (y + v) * _dimx + u;
727
728 for (int x = 0; x < width; x++) {
729 if (*raw)
730 *buf = calcTrasp(_palFinal[*raw], *buf);
731
732 buf++;
733 raw++;
734 }
735
736 buf += bufx - width;
737 }
738 } else {
739 for (int y = 0; y < height; y++) {
740 raw = _buf + (y + v) * _dimx + u;
741
742 for (int x = 0; x < width; x += 2) {
743 buf[0] = calcTrasp(_palFinal[raw[0]], buf[0]);
744 buf[1] = calcTrasp(_palFinal[raw[1]], buf[1]);
745
746 buf += 2;
747 raw += 2;
748 }
749
750 buf += bufx - width;
751 }
752 }
753
754 // Specify the drawn area
755 bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));
756 }
757
758 /****************************************************************************\
759 * RMGfxSourceBuffer8RLE Methods
760 \****************************************************************************/
761
762 byte RMGfxSourceBuffer8RLE::_megaRLEBuf[512 * 1024];
763
setAlphaBlendColor(int color)764 void RMGfxSourceBuffer8RLE::setAlphaBlendColor(int color) {
765 _alphaBlendColor = color;
766 }
767
RMGfxSourceBuffer8RLE()768 RMGfxSourceBuffer8RLE::RMGfxSourceBuffer8RLE() {
769 _alphaBlendColor = -1;
770 _bNeedRLECompress = true;
771 _buf = NULL;
772
773 _alphaR = _alphaG = _alphaB = 0;
774 }
775
~RMGfxSourceBuffer8RLE()776 RMGfxSourceBuffer8RLE::~RMGfxSourceBuffer8RLE() {
777 if (_buf != NULL) {
778 delete[] _buf;
779 _buf = NULL;
780 }
781 }
782
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)783 int RMGfxSourceBuffer8RLE::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
784 return RMGfxSourceBufferPal::init(buf, dimx, dimy, bLoadPalette);
785 }
786
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)787 void RMGfxSourceBuffer8RLE::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
788 if (_bNeedRLECompress) {
789 RMGfxSourceBufferPal::init(ds, dimx, dimy, bLoadPalette);
790 } else {
791 int size = ds.readSint32LE();
792 _buf = new byte[size];
793 ds.read(_buf, size);
794
795 _dimx = dimx;
796 _dimy = dimy;
797 }
798 }
799
preparePalette()800 void RMGfxSourceBuffer8RLE::preparePalette() {
801 // Invoke the parent method
802 RMGfxSourceBuffer8::preparePalette();
803
804 // Handle RGB alpha blending
805 if (_alphaBlendColor != -1) {
806 _alphaR = (_palFinal[_alphaBlendColor] >> 11) & 0x1F;
807 _alphaG = (_palFinal[_alphaBlendColor] >> 5) & 0x3F;
808 _alphaB = (_palFinal[_alphaBlendColor]) & 0x1F;
809 }
810 }
811
prepareImage()812 void RMGfxSourceBuffer8RLE::prepareImage() {
813 // Invoke the parent method
814 RMGfxSourceBuffer::prepareImage();
815
816 // Compress
817 compressRLE();
818 }
819
setAlreadyCompressed()820 void RMGfxSourceBuffer8RLE::setAlreadyCompressed() {
821 _bNeedRLECompress = false;
822 }
823
compressRLE()824 void RMGfxSourceBuffer8RLE::compressRLE() {
825 byte *cur;
826 byte curdata;
827 byte *src;
828
829 // Perform RLE compression for lines
830 cur = _megaRLEBuf;
831 src = _buf;
832 for (int y = 0; y < _dimy; y++) {
833 // Save the beginning of the line
834 byte *startline = cur;
835
836 // Leave space for the length of the line
837 cur += 2;
838
839 // It starts from the empty space
840 curdata = 0;
841 int rep = 0;
842 byte *startsrc = src;
843 for (int x = 0; x < _dimx;) {
844 if ((curdata == 0 && *src == 0) || (curdata == 1 && *src == _alphaBlendColor)
845 || (curdata == 2 && (*src != _alphaBlendColor && *src != 0))) {
846 src++;
847 rep++;
848 x++;
849 } else {
850 if (curdata == 0) {
851 rleWriteTrasp(cur, rep);
852 curdata++;
853 } else if (curdata == 1) {
854 rleWriteAlphaBlend(cur, rep);
855 curdata++;
856 } else {
857 rleWriteData(cur, rep, startsrc);
858 curdata = 0;
859 }
860
861 rep = 0;
862 startsrc = src;
863 }
864 }
865
866 // Pending data?
867 if (curdata == 1) {
868 rleWriteAlphaBlend(cur, rep);
869 rleWriteData(cur, 0, NULL);
870 }
871
872 if (curdata == 2) {
873 rleWriteData(cur, rep, startsrc);
874 }
875
876 // End of line
877 rleWriteEOL(cur);
878
879 // Write the length of the line
880 WRITE_LE_UINT16(startline, (uint16)(cur - startline));
881 }
882
883 // Delete the original image
884 delete[] _buf;
885
886 // Copy the compressed image
887 int bufSize = cur - _megaRLEBuf;
888 _buf = new byte[bufSize];
889 Common::copy(_megaRLEBuf, _megaRLEBuf + bufSize, _buf);
890 }
891
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)892 void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
893 byte *src;
894 uint16 *buf = bigBuf;
895 int u, v, width, height;
896
897 // Clipping
898 int x1 = prim->getDst()._x1;
899 int y1 = prim->getDst()._y1;
900 if (!clip2D(x1, y1, u, v, width, height, false, &bigBuf))
901 return;
902
903 // Go forward through the RLE lines
904 src = _buf;
905 for (int y = 0; y < v; y++)
906 src += READ_LE_UINT16(src);
907
908 // Calculate the position in the destination buffer
909 buf += y1 * bigBuf.getDimx();
910
911 // Loop
912 if (prim->isFlipped()) {
913 // Eliminate horizontal clipping
914 // width = m_dimx;
915 // x1=prim->getDst()._x1;
916
917 // Clipping
918 u = _dimx - (width + u);
919 x1 = (prim->getDst()._x1 + _dimx - 1) - u;
920
921 if (width > x1)
922 width = x1;
923
924 // Specify the drawn area
925 bigBuf.addDirtyRect(Common::Rect(x1 - width, y1, x1 + 1, y1 + height));
926
927 for (int y = 0; y < height; y++) {
928 // Decompression
929 rleDecompressLineFlipped(buf + x1, src + 2, u, width);
930
931 // Next line
932 src += READ_LE_UINT16(src);
933
934 // Skip to the next line
935 buf += bigBuf.getDimx();
936 }
937 } else {
938 // Specify the drawn area
939 bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
940
941 for (int y = 0; y < height; y++) {
942 // Decompression
943 rleDecompressLine(buf + x1, src + 2, u, width);
944
945 // Next line
946 src += READ_LE_UINT16(src);
947
948 // Skip to the next line
949 buf += bigBuf.getDimx();
950 }
951 }
952 }
953
954 /****************************************************************************\
955 * RMGfxSourceBuffer8RLEByte Methods
956 \****************************************************************************/
957
~RMGfxSourceBuffer8RLEByte()958 RMGfxSourceBuffer8RLEByte::~RMGfxSourceBuffer8RLEByte() {
959 }
960
rleWriteTrasp(byte * & cur,int rep)961 void RMGfxSourceBuffer8RLEByte::rleWriteTrasp(byte *&cur, int rep) {
962 assert(rep < 255);
963 *cur ++ = rep;
964 }
965
rleWriteAlphaBlend(byte * & cur,int rep)966 void RMGfxSourceBuffer8RLEByte::rleWriteAlphaBlend(byte *&cur, int rep) {
967 assert(rep < 255);
968 *cur ++ = rep;
969 }
970
rleWriteData(byte * & cur,int rep,byte * src)971 void RMGfxSourceBuffer8RLEByte::rleWriteData(byte *&cur, int rep, byte *src) {
972 assert(rep < 256);
973
974 *cur ++ = rep;
975 if (rep > 0) {
976 memcpy(cur, src, rep);
977 cur += rep;
978 src += rep;
979 }
980
981 return;
982 }
983
rleWriteEOL(byte * & cur)984 void RMGfxSourceBuffer8RLEByte::rleWriteEOL(byte *&cur) {
985 *cur ++ = 0xFF;
986 }
987
rleDecompressLine(uint16 * dst,byte * src,int nStartSkip,int nLength)988 void RMGfxSourceBuffer8RLEByte::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
989 int n;
990
991 if (nStartSkip == 0)
992 goto RLEByteDoTrasp;
993
994 while (1) {
995 assert(nStartSkip > 0);
996
997 // TRASP
998 n = *src++;
999 if (n == 0xFF)
1000 return;
1001
1002 if (n >= nStartSkip) {
1003 dst += n - nStartSkip;
1004 nLength -= n - nStartSkip;
1005 if (nLength > 0)
1006 goto RLEByteDoAlpha;
1007 else
1008 return;
1009 }
1010 nStartSkip -= n;
1011
1012
1013 assert(nStartSkip > 0);
1014
1015 // ALPHA
1016 n = *src++;
1017 if (n >= nStartSkip) {
1018 n -= nStartSkip;
1019 goto RLEByteDoAlpha2;
1020 }
1021 nStartSkip -= n;
1022
1023 assert(nStartSkip > 0);
1024
1025 // DATA
1026 n = *src++;
1027 if (n >= nStartSkip) {
1028 src += nStartSkip;
1029 n -= nStartSkip;
1030 goto RLEByteDoCopy2;
1031 }
1032 nStartSkip -= n;
1033 src += n;
1034 }
1035
1036 while (1) {
1037 RLEByteDoTrasp:
1038 // Get the trasp of s**t
1039 n = *src++;
1040
1041 // EOL?
1042 if (n == 0xFF)
1043 return;
1044
1045 dst += n;
1046 nLength -= n;
1047 if (nLength <= 0)
1048 return;
1049
1050 RLEByteDoAlpha:
1051 // Alpha
1052 n = *src++;
1053
1054 RLEByteDoAlpha2:
1055 if (n > nLength)
1056 n = nLength;
1057 for (int i = 0; i < n; i++) {
1058 int r = (*dst >> 11) & 0x1F;
1059 int g = (*dst >> 5) & 0x3F;
1060 int b = *dst & 0x1F;
1061
1062 r = (r >> 2) + (_alphaR >> 1);
1063 g = (g >> 2) + (_alphaG >> 1);
1064 b = (b >> 2) + (_alphaB >> 1);
1065
1066 *dst ++ = (r << 11) | (g << 5) | b;
1067 }
1068
1069 nLength -= n;
1070 if (!nLength)
1071 return;
1072 assert(nLength > 0);
1073
1074 //RLEByteDoCopy:
1075 // Copy the stuff
1076 n = *src++;
1077
1078 RLEByteDoCopy2:
1079 if (n > nLength)
1080 n = nLength;
1081
1082 for (int i = 0; i < n; i++)
1083 *dst ++ = _palFinal[*src++];
1084
1085 nLength -= n;
1086 if (!nLength)
1087 return;
1088 assert(nLength > 0);
1089 }
1090 }
1091
rleDecompressLineFlipped(uint16 * dst,byte * src,int nStartSkip,int nLength)1092 void RMGfxSourceBuffer8RLEByte::rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
1093 int n;
1094
1095 if (nStartSkip == 0)
1096 goto RLEByteFlippedDoTrasp;
1097
1098 while (1) {
1099 assert(nStartSkip > 0);
1100
1101 // TRASP
1102 n = *src++;
1103 if (n == 0xFF)
1104 return;
1105
1106 if (n >= nStartSkip) {
1107 dst -= n - nStartSkip;
1108 nLength -= n - nStartSkip;
1109 if (nLength > 0)
1110 goto RLEByteFlippedDoAlpha;
1111 else
1112 return;
1113 }
1114 nStartSkip -= n;
1115
1116
1117 assert(nStartSkip > 0);
1118
1119 // ALPHA
1120 n = *src++;
1121 if (n >= nStartSkip) {
1122 n -= nStartSkip;
1123 goto RLEByteFlippedDoAlpha2;
1124 }
1125 nStartSkip -= n;
1126
1127 assert(nStartSkip > 0);
1128
1129 // DATA
1130 n = *src++;
1131 if (n >= nStartSkip) {
1132 src += nStartSkip;
1133 n -= nStartSkip;
1134 goto RLEByteFlippedDoCopy2;
1135 }
1136 nStartSkip -= n;
1137 src += n;
1138 }
1139
1140 while (1) {
1141 RLEByteFlippedDoTrasp:
1142 // Get the trasp of s**t
1143 n = *src++;
1144
1145 // EOL?
1146 if (n == 0xFF)
1147 return;
1148
1149 dst -= n;
1150 nLength -= n;
1151 if (nLength <= 0)
1152 return;
1153
1154 RLEByteFlippedDoAlpha:
1155 // Alpha
1156 n = *src++;
1157
1158 RLEByteFlippedDoAlpha2:
1159 if (n > nLength)
1160 n = nLength;
1161 for (int i = 0; i < n; i++) {
1162 int r = (*dst >> 11) & 0x1F;
1163 int g = (*dst >> 5) & 0x3F;
1164 int b = *dst & 0x1F;
1165
1166 r = (r >> 2) + (_alphaR >> 1);
1167 g = (g >> 2) + (_alphaG >> 1);
1168 b = (b >> 2) + (_alphaB >> 1);
1169
1170 *dst-- = (r << 11) | (g << 5) | b;
1171 }
1172
1173 nLength -= n;
1174 if (!nLength)
1175 return;
1176 assert(nLength > 0);
1177
1178 //RLEByteFlippedDoCopy:
1179 // Copy the data
1180 n = *src++;
1181
1182 RLEByteFlippedDoCopy2:
1183 if (n > nLength)
1184 n = nLength;
1185
1186 for (int i = 0; i < n; i++)
1187 *dst-- = _palFinal[*src++];
1188
1189 nLength -= n;
1190 if (!nLength)
1191 return;
1192 assert(nLength > 0);
1193 }
1194 }
1195
1196 /****************************************************************************\
1197 * RMGfxSourceBuffer8RLEWord Methods
1198 \****************************************************************************/
1199
~RMGfxSourceBuffer8RLEWord()1200 RMGfxSourceBuffer8RLEWord::~RMGfxSourceBuffer8RLEWord() {
1201 }
1202
rleWriteTrasp(byte * & cur,int rep)1203 void RMGfxSourceBuffer8RLEWord::rleWriteTrasp(byte *&cur, int rep) {
1204 WRITE_LE_UINT16(cur, rep);
1205 cur += 2;
1206 }
1207
rleWriteAlphaBlend(byte * & cur,int rep)1208 void RMGfxSourceBuffer8RLEWord::rleWriteAlphaBlend(byte *&cur, int rep) {
1209 WRITE_LE_UINT16(cur, rep);
1210 cur += 2;
1211 }
1212
rleWriteData(byte * & cur,int rep,byte * src)1213 void RMGfxSourceBuffer8RLEWord::rleWriteData(byte *&cur, int rep, byte *src) {
1214 WRITE_LE_UINT16(cur, rep);
1215 cur += 2;
1216
1217 if (rep > 0) {
1218 memcpy(cur, src, rep);
1219 cur += rep;
1220 src += rep;
1221 }
1222 }
1223
rleWriteEOL(byte * & cur)1224 void RMGfxSourceBuffer8RLEWord::rleWriteEOL(byte *&cur) {
1225 *cur ++ = 0xFF;
1226 *cur ++ = 0xFF;
1227 }
1228
rleDecompressLine(uint16 * dst,byte * src,int nStartSkip,int nLength)1229 void RMGfxSourceBuffer8RLEWord::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
1230 int n;
1231
1232 if (nStartSkip == 0)
1233 goto RLEWordDoTrasp;
1234
1235 while (1) {
1236 assert(nStartSkip > 0);
1237
1238 // TRASP
1239 n = READ_LE_UINT16(src);
1240 src += 2;
1241
1242 if (n == 0xFFFF)
1243 return;
1244
1245 if (n >= nStartSkip) {
1246 dst += n - nStartSkip;
1247 nLength -= n - nStartSkip;
1248
1249 if (nLength > 0)
1250 goto RLEWordDoAlpha;
1251 else
1252 return;
1253 }
1254 nStartSkip -= n;
1255
1256 assert(nStartSkip > 0);
1257
1258 // ALPHA
1259 n = READ_LE_UINT16(src);
1260 src += 2;
1261
1262 if (n >= nStartSkip) {
1263 n -= nStartSkip;
1264 goto RLEWordDoAlpha2;
1265 }
1266 nStartSkip -= n;
1267
1268 // DATA
1269 n = READ_LE_UINT16(src);
1270 src += 2;
1271
1272 if (n >= nStartSkip) {
1273 src += nStartSkip;
1274 n -= nStartSkip;
1275 goto RLEWordDoCopy2;
1276 }
1277 nStartSkip -= n;
1278 src += n;
1279 }
1280
1281 while (1) {
1282 RLEWordDoTrasp:
1283 // Get the trasp of s**t
1284 n = READ_LE_UINT16(src);
1285 src += 2;
1286
1287 // EOL?
1288 if (n == 0xFFFF)
1289 return;
1290
1291 dst += n;
1292
1293 nLength -= n;
1294 if (nLength <= 0)
1295 return;
1296
1297 RLEWordDoAlpha:
1298 n = READ_LE_UINT16(src);
1299 src += 2;
1300
1301 RLEWordDoAlpha2:
1302 if (n > nLength)
1303 n = nLength;
1304
1305 for (int i = 0; i < n; i++) {
1306 int r = (*dst >> 11) & 0x1F;
1307 int g = (*dst >> 5) & 0x3F;
1308 int b = *dst & 0x1F;
1309
1310 r = (r >> 2) + (_alphaR >> 1);
1311 g = (g >> 2) + (_alphaG >> 1);
1312 b = (b >> 2) + (_alphaB >> 1);
1313
1314 *dst++ = (r << 11) | (g << 5) | b;
1315 }
1316
1317 nLength -= n;
1318 if (!nLength)
1319 return;
1320
1321 assert(nLength > 0);
1322
1323 //RLEWordDoCopy:
1324 // Copy the data
1325 n = READ_LE_UINT16(src);
1326 src += 2;
1327
1328 RLEWordDoCopy2:
1329 if (n > nLength)
1330 n = nLength;
1331
1332 for (int i = 0; i < n; i++)
1333 *dst++ = _palFinal[*src++];
1334
1335 nLength -= n;
1336 if (!nLength)
1337 return;
1338
1339 assert(nLength > 0);
1340 }
1341 }
1342
rleDecompressLineFlipped(uint16 * dst,byte * src,int nStartSkip,int nLength)1343 void RMGfxSourceBuffer8RLEWord::rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
1344 int n;
1345
1346 if (nStartSkip == 0)
1347 goto RLEWordFlippedDoTrasp;
1348
1349 while (1) {
1350 assert(nStartSkip > 0);
1351
1352 // TRASP
1353 n = READ_LE_UINT16(src);
1354 src += 2;
1355
1356 if (n == 0xFFFF)
1357 return;
1358
1359 if (n >= nStartSkip) {
1360 dst -= n - nStartSkip;
1361 nLength -= n - nStartSkip;
1362
1363 if (nLength > 0)
1364 goto RLEWordFlippedDoAlpha;
1365 else
1366 return;
1367 }
1368 nStartSkip -= n;
1369
1370 assert(nStartSkip > 0);
1371
1372 // ALPHA
1373 n = READ_LE_UINT16(src);
1374 src += 2;
1375
1376 if (n >= nStartSkip) {
1377 n -= nStartSkip;
1378 goto RLEWordFlippedDoAlpha2;
1379 }
1380 nStartSkip -= n;
1381
1382 // DATA
1383 n = READ_LE_UINT16(src);
1384 src += 2;
1385
1386 if (n >= nStartSkip) {
1387 src += nStartSkip;
1388 n -= nStartSkip;
1389 goto RLEWordFlippedDoCopy2;
1390 }
1391 nStartSkip -= n;
1392 src += n;
1393 }
1394
1395 while (1) {
1396 RLEWordFlippedDoTrasp:
1397 // Get the trasp of s**t
1398 n = READ_LE_UINT16(src);
1399 src += 2;
1400
1401 // EOL?
1402 if (n == 0xFFFF)
1403 return;
1404
1405 dst -= n;
1406
1407 nLength -= n;
1408 if (nLength <= 0)
1409 return;
1410
1411 RLEWordFlippedDoAlpha:
1412 n = READ_LE_UINT16(src);
1413 src += 2;
1414
1415 RLEWordFlippedDoAlpha2:
1416 if (n > nLength)
1417 n = nLength;
1418
1419 for (int i = 0; i < n; i++) {
1420 int r = (*dst >> 11) & 0x1F;
1421 int g = (*dst >> 5) & 0x3F;
1422 int b = *dst & 0x1F;
1423
1424 r = (r >> 2) + (_alphaR >> 1);
1425 g = (g >> 2) + (_alphaG >> 1);
1426 b = (b >> 2) + (_alphaB >> 1);
1427
1428 *dst-- = (r << 11) | (g << 5) | b;
1429 }
1430
1431 nLength -= n;
1432 if (!nLength)
1433 return;
1434
1435 assert(nLength > 0);
1436
1437 //RLEWordFlippedDoCopy:
1438 // Copy the data
1439 n = READ_LE_UINT16(src);
1440 src += 2;
1441
1442 RLEWordFlippedDoCopy2:
1443 if (n > nLength)
1444 n = nLength;
1445
1446 for (int i = 0; i < n; i++)
1447 *dst-- = _palFinal[*src++];
1448
1449 nLength -= n;
1450 if (!nLength)
1451 return;
1452
1453 assert(nLength > 0);
1454 }
1455 }
1456
1457 /****************************************************************************\
1458 * Methods for RMGfxSourceBuffer8RLEWord
1459 \****************************************************************************/
1460
~RMGfxSourceBuffer8RLEWordAB()1461 RMGfxSourceBuffer8RLEWordAB::~RMGfxSourceBuffer8RLEWordAB() {
1462 }
1463
rleDecompressLine(uint16 * dst,byte * src,int nStartSkip,int nLength)1464 void RMGfxSourceBuffer8RLEWordAB::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
1465 int n;
1466
1467 if (!GLOBALS._bCfgTransparence) {
1468 RMGfxSourceBuffer8RLEWord::rleDecompressLine(dst, src, nStartSkip, nLength);
1469 return;
1470 }
1471
1472 if (nStartSkip == 0)
1473 goto RLEWordDoTrasp;
1474
1475 while (1) {
1476 assert(nStartSkip > 0);
1477
1478 // TRASP
1479 n = READ_LE_UINT16(src);
1480 src += 2;
1481
1482 if (n == 0xFFFF)
1483 return;
1484
1485 if (n >= nStartSkip) {
1486 dst += n - nStartSkip;
1487 nLength -= n - nStartSkip;
1488
1489 if (nLength > 0)
1490 goto RLEWordDoAlpha;
1491 else
1492 return;
1493 }
1494 nStartSkip -= n;
1495
1496 assert(nStartSkip > 0);
1497
1498 // ALPHA
1499 n = READ_LE_UINT16(src);
1500 src += 2;
1501
1502 if (n >= nStartSkip) {
1503 n -= nStartSkip;
1504 goto RLEWordDoAlpha2;
1505 }
1506 nStartSkip -= n;
1507
1508 // DATA
1509 n = READ_LE_UINT16(src);
1510 src += 2;
1511
1512 if (n >= nStartSkip) {
1513 src += nStartSkip;
1514 n -= nStartSkip;
1515 goto RLEWordDoCopy2;
1516 }
1517 nStartSkip -= n;
1518 src += n;
1519 }
1520
1521 while (1) {
1522 RLEWordDoTrasp:
1523 // Get the trasp of s**t
1524 n = READ_LE_UINT16(src);
1525 src += 2;
1526
1527 // EOL?
1528 if (n == 0xFFFF)
1529 return;
1530
1531 dst += n;
1532
1533 nLength -= n;
1534 if (nLength <= 0)
1535 return;
1536
1537 RLEWordDoAlpha:
1538 n = READ_LE_UINT16(src);
1539 src += 2;
1540
1541 RLEWordDoAlpha2:
1542 if (n > nLength)
1543 n = nLength;
1544
1545 // @@@ SHOULD NOT BE THERE !!!!!
1546 for (int i = 0; i < n; i++) {
1547 int r = (*dst >> 11) & 0x1F;
1548 int g = (*dst >> 5) & 0x3F;
1549 int b = *dst & 0x1F;
1550
1551 r = (r >> 2) + (_alphaR >> 1);
1552 g = (g >> 2) + (_alphaG >> 1);
1553 b = (b >> 2) + (_alphaB >> 1);
1554
1555 *dst++ = (r << 11) | (g << 5) | b;
1556 }
1557
1558 nLength -= n;
1559 if (!nLength)
1560 return;
1561
1562 assert(nLength > 0);
1563
1564 //RLEWordDoCopy:
1565 // Copy the data
1566 n = READ_LE_UINT16(src);
1567 src += 2;
1568
1569 RLEWordDoCopy2:
1570 if (n > nLength)
1571 n = nLength;
1572
1573 for (int i = 0; i < n; i++) {
1574 int r = (*dst >> 11) & 0x1F;
1575 int g = (*dst >> 5) & 0x3F;
1576 int b = *dst & 0x1F;
1577
1578 int r2 = (_palFinal[*src] >> 11) & 0x1F;
1579 int g2 = (_palFinal[*src] >> 5) & 0x3F;
1580 int b2 = _palFinal[*src] & 0x1F;
1581
1582 r = (r >> 1) + (r2 >> 1);
1583 g = (g >> 1) + (g2 >> 1);
1584 b = (b >> 1) + (b2 >> 1);
1585
1586 *dst ++ = (r << 11) | (g << 5) | b;
1587 src++;
1588 }
1589
1590 nLength -= n;
1591 if (!nLength)
1592 return;
1593
1594 assert(nLength > 0);
1595 }
1596 }
1597
1598 /****************************************************************************\
1599 * Methods for RMGfxSourceBuffer8AA
1600 \****************************************************************************/
1601
1602 byte RMGfxSourceBuffer8AA::_megaAABuf[256 * 1024];
1603 byte RMGfxSourceBuffer8AA::_megaAABuf2[64 * 1024];
1604
prepareImage()1605 void RMGfxSourceBuffer8AA::prepareImage() {
1606 // Invoke the parent method
1607 RMGfxSourceBuffer::prepareImage();
1608
1609 // Prepare the buffer for anti-aliasing
1610 calculateAA();
1611 }
1612
calculateAA()1613 void RMGfxSourceBuffer8AA::calculateAA() {
1614 byte *src, *srcaa;
1615
1616 // First pass: fill the edges
1617 Common::fill(_megaAABuf, _megaAABuf + _dimx * _dimy, 0);
1618
1619 src = _buf;
1620 srcaa = _megaAABuf;
1621 for (int y = 0; y < _dimy; y++) {
1622 for (int x = 0; x < _dimx; x++) {
1623 if (*src == 0) {
1624 if ((y > 0 && src[-_dimx] != 0) ||
1625 (y < _dimy - 1 && src[_dimx] != 0) ||
1626 (x > 0 && src[-1] != 0) ||
1627 (x < _dimx - 1 && src[1] != 0))
1628 *srcaa = 1;
1629 }
1630
1631 src++;
1632 srcaa++;
1633 }
1634 }
1635
1636 src = _buf;
1637 srcaa = _megaAABuf;
1638 for (int y = 0; y < _dimy; y++) {
1639 for (int x = 0; x < _dimx; x++) {
1640 if (*src != 0) {
1641 if ((y > 0 && srcaa[-_dimx] == 1) ||
1642 (y < _dimy - 1 && srcaa[_dimx] == 1) ||
1643 (x > 0 && srcaa[-1] == 1) ||
1644 (x < _dimx - 1 && srcaa[1] == 1))
1645 *srcaa = 2;
1646 }
1647
1648 src++;
1649 srcaa++;
1650 }
1651 }
1652
1653 if (_aabuf != NULL)
1654 delete[] _aabuf;
1655
1656 _aabuf = new byte[_dimx * _dimy];
1657 memcpy(_aabuf, _megaAABuf, _dimx * _dimy);
1658 }
1659
RMGfxSourceBuffer8AA()1660 RMGfxSourceBuffer8AA::RMGfxSourceBuffer8AA() : RMGfxSourceBuffer8() {
1661 _aabuf = NULL;
1662 }
1663
~RMGfxSourceBuffer8AA()1664 RMGfxSourceBuffer8AA::~RMGfxSourceBuffer8AA() {
1665 if (_aabuf != NULL)
1666 delete[] _aabuf;
1667 }
1668
drawAA(RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1669 void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1670 byte *src;
1671 uint16 *mybuf;
1672 uint16 *buf;
1673 int u, v, width, height;
1674
1675 // Clip the sprite
1676 int x1 = prim->getDst()._x1;
1677 int y1 = prim->getDst()._y1;
1678 if (!clip2D(x1, y1, u, v, width, height, false, &bigBuf))
1679 return;
1680
1681 // Go forward through the RLE lines
1682 src = _buf;
1683 for (int y = 0; y < v; y++)
1684 src += READ_LE_UINT16(src);
1685
1686 // Eliminate horizontal clipping
1687 if (prim->isFlipped()) {
1688 u = _dimx - (width + u);
1689 x1 = (prim->getDst()._x1 + _dimx - 1) - u;
1690
1691 if (width > x1)
1692 width = x1;
1693
1694 // Specify the drawn area
1695 bigBuf.addDirtyRect(Common::Rect(x1 - width, y1, x1 + 1, y1 + height));
1696 } else {
1697 // Specify the drawn area
1698 bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
1699 }
1700
1701 //width = _dimx;
1702 //x1 = prim->getDst()._x1;
1703
1704 // Position into the destination buffer
1705 buf = bigBuf;
1706 buf += y1 * bigBuf.getDimx();
1707
1708 int step;
1709 if (prim->isFlipped())
1710 step = -1;
1711 else
1712 step = 1;
1713
1714 // Loop
1715 buf += bigBuf.getDimx(); // Skip the first line
1716 for (int y = 1; y < height - 1; y++) {
1717 // if (prim->isFlipped())
1718 // mybuf=&buf[x1+m_dimx-1];
1719 // else
1720 mybuf = &buf[x1];
1721
1722 for (int x = 0; x < width; x++, mybuf += step) {
1723 if (_aabuf[(y + v) * _dimx + x + u] == 2 && x != 0 && x != width - 1) {
1724 int r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
1725 int g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
1726 int b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
1727
1728 r += GETRED(mybuf[0]);
1729 g += GETGREEN(mybuf[0]);
1730 b += GETBLUE(mybuf[0]);
1731
1732 r /= 5;
1733 g /= 5;
1734 b /= 5;
1735
1736 mybuf[0] = (r << 11) | (g << 5) | b;
1737 }
1738 }
1739
1740 // Skip to the next line
1741 buf += bigBuf.getDimx();
1742 }
1743
1744 // Position into the destination buffer
1745 buf = bigBuf;
1746 buf += y1 * bigBuf.getDimx();
1747
1748 // Looppone
1749 buf += bigBuf.getDimx();
1750 for (int y = 1; y < height - 1; y++) {
1751 // if (prim->isFlipped())
1752 // mybuf=&buf[x1+m_dimx-1];
1753 // else
1754 mybuf = &buf[x1];
1755
1756 for (int x = 0; x < width; x++, mybuf += step) {
1757 if (_aabuf[(y + v) * _dimx + x + u] == 1 && x != 0 && x != width - 1) {
1758 int r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
1759 int g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
1760 int b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
1761
1762 r += GETRED(mybuf[0]) * 2;
1763 g += GETGREEN(mybuf[0]) * 2;
1764 b += GETBLUE(mybuf[0]) * 2;
1765
1766 r /= 6;
1767 g /= 6;
1768 b /= 6;
1769
1770 mybuf[0] = (r << 11) | (g << 5) | b;
1771 }
1772 }
1773
1774 // Skip to the next line
1775 buf += bigBuf.getDimx();
1776 }
1777 }
1778
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1779 void RMGfxSourceBuffer8AA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1780 CORO_BEGIN_CONTEXT;
1781 CORO_END_CONTEXT(_ctx);
1782
1783 CORO_BEGIN_CODE(_ctx);
1784
1785 CORO_INVOKE_2(RMGfxSourceBuffer8::draw, bigBuf, prim);
1786 drawAA(bigBuf, prim);
1787
1788 CORO_END_CODE;
1789 }
1790
1791 /****************************************************************************\
1792 * RMGfxSourceBuffer8RLEAA Methods
1793 \****************************************************************************/
1794
~RMGfxSourceBuffer8RLEByteAA()1795 RMGfxSourceBuffer8RLEByteAA::~RMGfxSourceBuffer8RLEByteAA() {
1796 }
1797
prepareImage()1798 void RMGfxSourceBuffer8RLEByteAA::prepareImage() {
1799 RMGfxSourceBuffer::prepareImage();
1800 calculateAA();
1801 compressRLE();
1802 }
1803
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1804 void RMGfxSourceBuffer8RLEByteAA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1805 CORO_BEGIN_CONTEXT;
1806 CORO_END_CONTEXT(_ctx);
1807
1808 CORO_BEGIN_CODE(_ctx);
1809
1810 CORO_INVOKE_2(RMGfxSourceBuffer8RLE::draw, bigBuf, prim);
1811 if (GLOBALS._bCfgAntiAlias)
1812 drawAA(bigBuf, prim);
1813
1814 CORO_END_CODE;
1815 }
1816
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)1817 int RMGfxSourceBuffer8RLEByteAA::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
1818 return RMGfxSourceBuffer8RLE::init(buf, dimx, dimy, bLoadPalette);
1819 }
1820
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)1821 void RMGfxSourceBuffer8RLEByteAA::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
1822 RMGfxSourceBuffer8RLE::init(ds, dimx, dimy, bLoadPalette);
1823
1824 if (!_bNeedRLECompress) {
1825 // Load the anti-aliasing mask
1826 _aabuf = new byte[dimx * dimy];
1827 ds.read(_aabuf, dimx * dimy);
1828 }
1829 }
1830
~RMGfxSourceBuffer8RLEWordAA()1831 RMGfxSourceBuffer8RLEWordAA::~RMGfxSourceBuffer8RLEWordAA() {
1832 }
1833
prepareImage()1834 void RMGfxSourceBuffer8RLEWordAA::prepareImage() {
1835 RMGfxSourceBuffer::prepareImage();
1836 calculateAA();
1837 compressRLE();
1838 }
1839
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1840 void RMGfxSourceBuffer8RLEWordAA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1841 CORO_BEGIN_CONTEXT;
1842 CORO_END_CONTEXT(_ctx);
1843
1844 CORO_BEGIN_CODE(_ctx);
1845
1846 CORO_INVOKE_2(RMGfxSourceBuffer8RLE::draw, bigBuf, prim);
1847 if (GLOBALS._bCfgAntiAlias)
1848 drawAA(bigBuf, prim);
1849
1850 CORO_END_CODE;
1851 }
1852
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)1853 int RMGfxSourceBuffer8RLEWordAA::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
1854 return RMGfxSourceBuffer8RLE::init(buf, dimx, dimy, bLoadPalette);
1855 }
1856
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)1857 void RMGfxSourceBuffer8RLEWordAA::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
1858 RMGfxSourceBuffer8RLE::init(ds, dimx, dimy, bLoadPalette);
1859
1860 if (!_bNeedRLECompress) {
1861 // Load the anti-aliasing mask
1862 _aabuf = new byte[dimx * dimy];
1863 ds.read(_aabuf, dimx * dimy);
1864 }
1865 }
1866
1867 /****************************************************************************\
1868 * RMGfxSourceBuffer16 Methods
1869 \****************************************************************************/
1870
RMGfxSourceBuffer16(bool bTrasp0)1871 RMGfxSourceBuffer16::RMGfxSourceBuffer16(bool bTrasp0) {
1872 _bTrasp0 = bTrasp0;
1873 }
1874
~RMGfxSourceBuffer16()1875 RMGfxSourceBuffer16::~RMGfxSourceBuffer16() {
1876 }
1877
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1878 void RMGfxSourceBuffer16::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1879 uint16 *buf = bigBuf;
1880 uint16 *raw = (uint16 *)_buf;
1881
1882 int dimx = _dimx;
1883 int dimy = _dimy;
1884 int u = 0;
1885 int v = 0;
1886 int x1 = 0;
1887 int y1 = 0;
1888
1889 if (prim->haveSrc()) {
1890 u = prim->getSrc()._x1;
1891 v = prim->getSrc()._y1;
1892 dimx = prim->getSrc().width();
1893 dimy = prim->getSrc().height();
1894 }
1895
1896 if (prim->haveDst()) {
1897 x1 = prim->getDst()._x1;
1898 y1 = prim->getDst()._y1;
1899 }
1900
1901 if (!clip2D(x1, y1, u, v, dimx, dimy, true, &bigBuf))
1902 return;
1903
1904 raw += v * _dimx + u;
1905 buf += y1 * bigBuf.getDimx() + x1;
1906
1907 if (_bTrasp0) {
1908 for (int y = 0; y < dimy; y++) {
1909 for (int x = 0; x < dimx;) {
1910 while (x < dimx && raw[x] == 0)
1911 x++;
1912
1913 while (x < dimx && raw[x] != 0) {
1914 buf[x] = raw[x];
1915 x++;
1916 }
1917 }
1918
1919 raw += _dimx;
1920 buf += bigBuf.getDimx();
1921 }
1922 } else {
1923 for (int y = 0; y < dimy; y++) {
1924 Common::copy(raw, raw + dimx, buf);
1925 buf += bigBuf.getDimx();
1926 raw += _dimx;
1927 }
1928 }
1929
1930 // Specify the drawn area
1931 bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + dimx, y1 + dimy));
1932 }
1933
prepareImage()1934 void RMGfxSourceBuffer16::prepareImage() {
1935 // Color space conversion if necessary!
1936 uint16 *buf = (uint16 *)_buf;
1937
1938 // convert 555 to 565
1939 for (int i = 0; i < _dimx * _dimy; i++) {
1940 uint16 pixel = FROM_LE_16(buf[i]);
1941 int r = (pixel >> 10) & 0x1F;
1942 int g = (pixel >> 5) & 0x1F;
1943 int b = pixel & 0x1F;
1944
1945 pixel = (r << 11) | (g << 6) | b;
1946
1947 buf[i] = pixel;
1948 }
1949 }
1950
RMGfxSourceBuffer16(int dimx,int dimy)1951 RMGfxSourceBuffer16::RMGfxSourceBuffer16(int dimx, int dimy)
1952 : RMGfxBuffer(dimx, dimy, 16) {
1953 setPriority(0);
1954 _bTrasp0 = false;
1955 }
1956
1957 /**
1958 * Returns the number of bits per pixel of the surface
1959 *
1960 * @returns Bit per pixel
1961 */
getBpp()1962 int RMGfxSourceBuffer16::getBpp() {
1963 return 16;
1964 }
1965
create(int dimx,int dimy)1966 void RMGfxSourceBuffer16::create(int dimx, int dimy) {
1967 RMGfxBuffer::create(dimx, dimy, 16);
1968 }
1969
1970 /****************************************************************************\
1971 * RMGfxBox Methods
1972 \****************************************************************************/
1973
removeThis(CORO_PARAM,bool & result)1974 void RMGfxBox::removeThis(CORO_PARAM, bool &result) {
1975 result = true;
1976 }
1977
setColor(byte r,byte g,byte b)1978 void RMGfxBox::setColor(byte r, byte g, byte b) {
1979 r >>= 3;
1980 g >>= 3;
1981 b >>= 3;
1982 // These are hard-coded colors, so we convert 555 to 565.
1983 _wFillColor = (r << 11) | (g << 6) | b;
1984 }
1985
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1986 void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1987 uint16 *buf = bigBuf;
1988 RMRect rcDst;
1989
1990 // It takes the destination rectangle
1991 rcDst = prim->getDst();
1992 buf += rcDst._y1 * bigBuf.getDimx() + rcDst._x1;
1993
1994 // Loop through the pixels
1995 for (int j = 0; j < rcDst.height(); j++) {
1996 for (int i = 0; i < rcDst.width(); i++)
1997 *buf++ = _wFillColor;
1998
1999 buf += bigBuf.getDimx() - rcDst.width();
2000 }
2001
2002 // Specify the drawn area
2003 bigBuf.addDirtyRect(rcDst);
2004 }
2005
2006 /****************************************************************************\
2007 * RMGfxClearTask Methods
2008 \****************************************************************************/
2009
priority()2010 int RMGfxClearTask::priority() {
2011 // Maximum priority (must be done first)
2012 return 1;
2013 }
2014
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive *)2015 void RMGfxClearTask::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *) {
2016 // Clean the target buffer
2017 Common::fill((byte *)bigBuf, (byte *)bigBuf + (bigBuf.getDimx() * bigBuf.getDimy() * 2), 0x0);
2018 bigBuf.addDirtyRect(Common::Rect(bigBuf.getDimx(), bigBuf.getDimy()));
2019 }
2020
removeThis(CORO_PARAM,bool & result)2021 void RMGfxClearTask::removeThis(CORO_PARAM, bool &result) {
2022 // The task is fine to be removed
2023 result = true;
2024 }
2025
2026 /****************************************************************************\
2027 * RMGfxPrimitive Methods
2028 \****************************************************************************/
2029
RMGfxPrimitive()2030 RMGfxPrimitive::RMGfxPrimitive() {
2031 _bFlag = 0;
2032 _task = NULL;
2033 _src.setEmpty();
2034 _dst.setEmpty();
2035 _bStretch = false;
2036 }
2037
RMGfxPrimitive(RMGfxTask * task)2038 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task) {
2039 _task = task;
2040 _bFlag = 0;
2041 _bStretch = false;
2042 }
2043
RMGfxPrimitive(RMGfxTask * task,const RMRect & src,RMRect & dst)2044 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &src, RMRect &dst) {
2045 _task = task;
2046 _src = src;
2047 _dst = dst;
2048 _bFlag = 0;
2049 _bStretch = (src.width() != dst.width() || src.height() != dst.height());
2050 }
2051
RMGfxPrimitive(RMGfxTask * task,const RMPoint & src,RMRect & dst)2052 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &src, RMRect &dst) {
2053 _task = task;
2054 _src.topLeft() = src;
2055 _dst = dst;
2056 _bFlag = 0;
2057 _bStretch = false;
2058 }
2059
RMGfxPrimitive(RMGfxTask * task,const RMPoint & src,RMPoint & dst)2060 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &src, RMPoint &dst) {
2061 _task = task;
2062 _src.topLeft() = src;
2063 _dst.topLeft() = dst;
2064 _bFlag = 0;
2065 _bStretch = false;
2066 }
2067
RMGfxPrimitive(RMGfxTask * task,const RMRect & src,RMPoint & dst)2068 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &src, RMPoint &dst) {
2069 _task = task;
2070 _src = src;
2071 _dst.topLeft() = dst;
2072 _bFlag = 0;
2073 _bStretch = false;
2074 }
2075
RMGfxPrimitive(RMGfxTask * task,const RMRect & dst)2076 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &dst) {
2077 _task = task;
2078 _dst = dst;
2079 _src.setEmpty();
2080 _bFlag = 0;
2081 _bStretch = false;
2082 }
2083
RMGfxPrimitive(RMGfxTask * task,const RMPoint & dst)2084 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &dst) {
2085 _task = task;
2086 _dst.topLeft() = dst;
2087 _src.setEmpty();
2088 _bFlag = 0;
2089 _bStretch = false;
2090 }
2091
~RMGfxPrimitive()2092 RMGfxPrimitive::~RMGfxPrimitive() {
2093 }
2094
setFlag(byte bFlag)2095 void RMGfxPrimitive::setFlag(byte bFlag) {
2096 _bFlag = bFlag;
2097 }
2098
setTask(RMGfxTask * task)2099 void RMGfxPrimitive::setTask(RMGfxTask *task) {
2100 _task = task;
2101 }
2102
setSrc(const RMRect & src)2103 void RMGfxPrimitive::setSrc(const RMRect &src) {
2104 _src = src;
2105 }
2106
setSrc(const RMPoint & src)2107 void RMGfxPrimitive::setSrc(const RMPoint &src) {
2108 _src.topLeft() = src;
2109 }
2110
setDst(const RMRect & dst)2111 void RMGfxPrimitive::setDst(const RMRect &dst) {
2112 _dst = dst;
2113 }
2114
setDst(const RMPoint & dst)2115 void RMGfxPrimitive::setDst(const RMPoint &dst) {
2116 _dst.topLeft() = dst;
2117 }
2118
setStretch(bool bStretch)2119 void RMGfxPrimitive::setStretch(bool bStretch) {
2120 _bStretch = bStretch;
2121 }
2122
haveDst()2123 bool RMGfxPrimitive::haveDst() {
2124 return !_dst.isEmpty();
2125 }
2126
getDst()2127 RMRect &RMGfxPrimitive::getDst() {
2128 return _dst;
2129 }
2130
haveSrc()2131 bool RMGfxPrimitive::haveSrc() {
2132 return !_src.isEmpty();
2133 }
2134
getSrc()2135 RMRect &RMGfxPrimitive::getSrc() {
2136 return _src;
2137 }
2138
2139 /**
2140 * Flags
2141 */
isFlipped()2142 bool RMGfxPrimitive::isFlipped() {
2143 return _bFlag & 1;
2144 }
2145
2146 /**
2147 * Duplicate
2148 */
duplicate()2149 RMGfxPrimitive *RMGfxPrimitive::duplicate() {
2150 return new RMGfxPrimitive(*this);
2151 }
2152
2153 } // End of namespace Tony
2154