Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

blitter.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2002 Xavier Trochu
00003 
00004 This software is provided 'as-is', without any express or implied warranty. In no event
00005 will the authors be held liable for any damages arising from the use of this software.
00006 
00007 Permission is granted to anyone to use this software for any purpose, including commercial
00008 applications, and to alter it and redistribute it freely, subject to the following
00009 restrictions:
00010 
00011 1. The origin of this software must not be misrepresented; you must not claim that you
00012    wrote the original software. If you use this software in a product, an acknowledgment
00013    in the product documentation would be appreciated but is not required.
00014 
00015 2. Altered source versions must be plainly marked as such, and must not be misrepresented 
00016    as being the original software.
00017 
00018 3. This notice may not be removed or altered from any source distribution.
00019 */
00020 #include "blitter.h"
00021 #include "chunck.h"
00022 #include <algorithm>
00023 #include <cstring> // for memcpy
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         //~ _offset += _src.left() + _clip.get_x() - _cur.get_x();
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             //~ _offset += _src.left() + _clip.get_x() - _cur.get_x() - x;
00067         } else {
00068             //~ _offset += x;
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     //~ if(y != 0) {
00077         //~ _cur.set(_src.left() + x*4, _cur.get_y() + y*4);
00078     //~ } else {
00079         //~ _cur.get_x() += x*4;
00080         //~ if(_cur.get_x() >= _src.right()) {
00081             //~ _cur.set(_src.left(), _cur.get_y()+3);
00082         //~ }
00083     //~ }
00084     //~ _offset = _ptr + _clip.get_x() * _cur.get_y()  + _cur.get_x();
00085     //~ _outside = ! _src.is_inside(_cur); 
00086     advance(x*4, y*4);
00087     //~ cout << "blitter::advance_block(" << x << ", " << y << ") == " << _cur << ", " << _outside << ", " << static_cast<int>(_offset - _ptr) << endl;
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()) // This is clipping
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()) // This is clipping
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()) // This is clipping
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()) // This is clipping
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         //~ unsigned int  src = src.get_dreinterpret_cast<unsigned int *>(data);
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()) // This is clipping
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 }

Generated on Fri Aug 9 22:54:29 2002 for san_player by doxygen1.2.16