00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "blitter.h"
00021 #include "chunck.h"
00022 #include <algorithm>
00023 #include <cstring>
00024
00025 #ifdef DEBUG_CLIPPER
00026 #include <iostream>
00027 #endif
00028
00029 using namespace std;
00030
00031 blitter::blitter(char * ptr, const point & dstsize, const rect & src) throw() :
00032 _ptr(ptr),
00033 _clip(dstsize),
00034 _src(src),
00035 _cur(src.left(), src.top()),
00036 _outside(false) {
00037 #ifdef DEBUG_CLIPPER
00038 _clipped = 0;
00039 _clipped_block = 0;
00040 cout << "blitter::blitter(" << dstsize << ", " << src << ") called" << endl;
00041 #endif
00042 assert(_ptr);
00043 assert(_clip.get_x() > 0 && _clip.get_y() > 0);
00044 assert(_src.width() > 0 && _src.height() > 0);
00045 assert(_src.left() < _clip.get_x() && _src.right() <= _clip.get_x());
00046 assert(_src.top() < _clip.get_y() && _src.bottom() <= _clip.get_y());
00047 _offset = _ptr + _clip.get_x() * _cur.get_y() + _cur.get_x();
00048 }
00049
00050 blitter::~blitter() {
00051 #ifdef DEBUG_CLIPPER
00052 if(_clipped || _clipped_block) {
00053 cout << "blitter clipped " << _clipped << " pixels and " << _clipped_block << " blocks" << endl;
00054 }
00055 #endif
00056 }
00057
00058 void blitter::advance(int x, int y) throw() {
00059 if(y != 0) {
00060
00061 _cur.set(_src.left() + x, _cur.get_y() + y);
00062 } else {
00063 _cur.get_x() += x;
00064 if(_cur.get_x() >= _src.right()) {
00065 _cur.set(_src.left(), _cur.get_y()+1);
00066
00067 } else {
00068
00069 }
00070 }
00071 _offset = _ptr + _clip.get_x() * _cur.get_y() + _cur.get_x();
00072 _outside = ! _src.is_inside(_cur);
00073 }
00074
00075 void blitter::advance_block(int x, int y) throw() {
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 advance(x*4, y*4);
00087
00088 }
00089
00090 void blitter::put(char data) throw(exception) {
00091 if(!_outside) {
00092 *_offset = data;
00093 advance();
00094 }
00095 #ifdef DEBUG_CLIPPER
00096 else _clipped ++;
00097 #endif
00098 }
00099
00100 void blitter::put(char data, unsigned int len) throw(exception) {
00101 while(len) {
00102 if(_outside) {
00103 #ifdef DEBUG_CLIPPER
00104 _clipped += len;
00105 #endif
00106 break;
00107 }
00108 int l = min(static_cast<int>(len), min(_clip.get_x() - _cur.get_x(), _src.right() - _cur.get_x()));
00109 len -= l;
00110 memset(_offset, data, l);
00111 advance(l);
00112 }
00113 }
00114
00115 void blitter::blit(char * ptr, unsigned int len) throw(exception) {
00116 while(len) {
00117 if(_outside) {
00118 #ifdef DEBUG_CLIPPER
00119 _clipped += len;
00120 #endif
00121 break;
00122 }
00123 int l = min(static_cast<int>(len), min(_clip.get_x() - _cur.get_x(), _src.right() - _cur.get_x()));
00124 len -= l;
00125 memcpy(_offset, ptr, l);
00126 ptr += l;
00127 advance(l);
00128 }
00129 }
00130
00131 void blitter::blit(chunck & src, unsigned int len) throw(exception) {
00132 while(len) {
00133 if(_outside) {
00134 #ifdef DEBUG_CLIPPER
00135 _clipped += len;
00136 #endif
00137 break;
00138 }
00139 int l = min(static_cast<int>(len), min(_clip.get_x() -_cur.get_x(), _src.right() - _cur.get_x()));
00140 len -= l;
00141 src.read(_offset, l);
00142 advance(l);
00143 }
00144 }
00145
00146 void blitter::put_block(unsigned int data) throw(exception) {
00147 if(_cur.get_x() + 3 < _src.right() && _cur.get_y() + 3 < _src.bottom())
00148 {
00149 assert((_clip.get_x() & 3) == 0);
00150 unsigned int * dst = reinterpret_cast<unsigned int *>(_offset);
00151 int line_size = _clip.get_x() >> 2;
00152 *dst = data; dst += line_size;
00153 *dst = data; dst += line_size;
00154 *dst = data; dst += line_size;
00155 *dst = data;
00156 #ifdef DEBUG_CLIPPER
00157 } else {
00158 _clipped_block ++;
00159 #endif
00160 }
00161 advance_block();
00162 }
00163
00164 void blitter::put_block(unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4) throw(exception) {
00165 if(_cur.get_x() + 3 < _src.right() && _cur.get_y() + 3 < _src.bottom())
00166 {
00167 assert((_clip.get_x() & 3) == 0);
00168 unsigned int * dst = reinterpret_cast<unsigned int *>(_offset);
00169 int line_size = _clip.get_x() >> 2;
00170 *dst = d4; dst += line_size;
00171 *dst = d3; dst += line_size;
00172 *dst = d2; dst += line_size;
00173 *dst = d1;
00174 #ifdef DEBUG_CLIPPER
00175 } else {
00176 _clipped_block ++;
00177 #endif
00178 }
00179 advance_block();
00180 }
00181
00182 void blitter::put_block(unsigned char * data) throw(exception) {
00183 if(_cur.get_x() + 3 < _src.right() && _cur.get_y() + 3 < _src.bottom())
00184 {
00185 assert((_clip.get_x() & 3) == 0);
00186 unsigned int * dst = reinterpret_cast<unsigned int *>(_offset);
00187 int line_size = _clip.get_x() >> 2;
00188 unsigned int * src = reinterpret_cast<unsigned int *>(data);
00189 *dst = *src++; dst += line_size;
00190 *dst = *src++; dst += line_size;
00191 *dst = *src++; dst += line_size;
00192 *dst = *src++;
00193 #ifdef DEBUG_CLIPPER
00194 } else {
00195 _clipped_block ++;
00196 #endif
00197 }
00198 advance_block();
00199 }
00200
00201 void blitter::put_block(chunck & src) throw(exception) {
00202 if(_cur.get_x() + 3 < _src.right() && _cur.get_y() + 3 < _src.bottom())
00203 {
00204 assert((_clip.get_x() & 3) == 0);
00205 unsigned int * dst = reinterpret_cast<unsigned int *>(_offset);
00206 int line_size = _clip.get_x() >> 2;
00207
00208 *dst = src.get_dword(); dst += line_size;
00209 *dst = src.get_dword(); dst += line_size;
00210 *dst = src.get_dword(); dst += line_size;
00211 *dst = src.get_dword();
00212 #ifdef DEBUG_CLIPPER
00213 } else {
00214 _clipped_block ++;
00215 #endif
00216 }
00217 advance_block();
00218 }
00219
00220 void blitter::block_copy(int offset) {
00221 if(_cur.get_x() + 3 < _src.right() && _cur.get_y() + 3 < _src.bottom())
00222 {
00223 char * dst = _offset;
00224 *reinterpret_cast<unsigned int *>(dst) = *reinterpret_cast<unsigned int *>(dst + offset);
00225 dst += _clip.get_x();
00226 *reinterpret_cast<unsigned int *>(dst) = *reinterpret_cast<unsigned int *>(dst + offset);
00227 dst += _clip.get_x();
00228 *reinterpret_cast<unsigned int *>(dst) = *reinterpret_cast<unsigned int *>(dst + offset);
00229 dst += _clip.get_x();
00230 *reinterpret_cast<unsigned int *>(dst) = *reinterpret_cast<unsigned int *>(dst + offset);
00231 #ifdef DEBUG_CLIPPER
00232 } else {
00233 _clipped_block ++;
00234 #endif
00235 }
00236 advance_block();
00237 }