Функция BltSurface()
Функция BltSurface() класса DirectDrawWin оказывается более гибкой и удобной по сравнению с функциями DirectDrawSurface::Blt() и BltFast(). Мы уже видели, как BltSurface() используется внутри функции BounceWin::DrawScene(), а сейчас рассмотрим саму функцию.
Функция BltSurface() требует передачи четырех аргументов, а пятый аргумент необязателен. Первые два аргумента представляют собой указатели на поверхности — источник и приемник. Следующие два аргумента — координаты x и y, определяющие положение копируемой области на приемнике. По умолчанию блиттинг выполняется без цветовых ключей, однако их можно активизировать с помощью необязательного пятого параметра. Код функции BltSurface() приведен в листинге 3.3.
Листинг 3.3. Функция BltSurface()
BOOL DirectDrawWin::BltSurface( LPDIRECTDRAWSURFACE destsurf, LPDIRECTDRAWSURFACE srcsurf, int x, int y, BOOL srccolorkey ) { if (destsurf==0 || srcsurf==0) return FALSE;
BOOL use_fastblt=TRUE; DDSURFACEDESC destsurfdesc; ZeroMemory( &destsurfdesc, sizeof(destsurfdesc) ); destsurfdesc.dwSize = sizeof(destsurfdesc); destsurf->GetSurfaceDesc( &destsurfdesc ); CRect destrect; destrect.left=0; destrect.top=0; destrect.right=destsurfdesc.dwWidth; destrect.bottom=destsurfdesc.dwHeight; DDSURFACEDESC srcsurfdesc; ZeroMemory( &srcsurfdesc, sizeof(srcsurfdesc) ); srcsurfdesc.dwSize = sizeof(srcsurfdesc); srcsurf->GetSurfaceDesc( &srcsurfdesc ); CRect srcrect; srcrect.left=0; srcrect.top=0; srcrect.right=srcsurfdesc.dwWidth; srcrect.bottom=srcsurfdesc.dwHeight; // Проверить, нужно ли что-нибудь делать... if (x+srcrect.left>=destrect.right) return FALSE; if (y+srcrect.top>=destrect.bottom) return FALSE; if (x+srcrect.right<=destrect.left) return FALSE; if (y+srcrect.bottom<=destrect.top) return FALSE; // При необходимости выполнить отсечение // для прямоугольной области источника if (x+srcrect.right>destrect.right) srcrect.right-=x+srcrect.right-destrect.right; if (y+srcrect.bottom>destrect.bottom) srcrect.bottom-=y+srcrect.bottom-destrect.bottom; CRect dr; if (x<0) { srcrect.left=-x; x=0; dr.left=x; dr.top=y; dr.right=x+srcrect.Width(); dr.bottom=y+srcrect.Height(); use_fastblt=FALSE; } if (y<0) { srcrect.top=-y; y=0; dr.left=x; dr.top=y; dr.right=x+srcrect.Width(); dr.bottom=y+srcrect.Height(); use_fastblt=FALSE; } DWORD flags; if (use_fastblt) { flags=DDBLTFAST_WAIT; if (srccolorkey) flags |= DDBLTFAST_SRCCOLORKEY; destsurf->BltFast( x, y, srcsurf, &srcrect, flags ); } else { flags=DDBLT_WAIT; if (srccolorkey) flags |= DDBLT_KEYSRC; destsurf->Blt( &dr, srcsurf, &srcrect, flags, 0 ); } return TRUE; } |
br>
Сначала функция BltSurface() проверяет указатели на поверхности. Если хотя бы один из них равен нулю, функция возвращает FALSE, тем самым сообщая о неудаче. Если проверка прошла успешно, два объекта CRect инициализируются в соответствии с размерами поверхностей, полученными с помощью функции DirectDrawSurface::GetSurfaceDesc().
Затем BltSurface() проверяет, что попадает ли точка назначения в границы приемника. Если координаты x и y таковы, что копия не пересекается с поверхностью приемника, блиттинг не нужен, поэтому мы просто выходим из функции.
Если же с точкой назначения все в порядке, функция проверяет, нужно ли выполнять отсечение. Если отсечение не требуется, блит-операция для достижения максимального быстродействия выполняется функцией BltFast(). Если отсечение все же необходимо, возможно, придется пользоваться функцией Blt().
Если отсечение выполняется по правому или нижнему краю источника, функция BltFast() справится с задачей и обрежет выступающую часть копируемой области. Если же отсечение происходит по верхнему или левому краю, приходится работать с функцией Blt(), потому что BltFast() не позволяет задать прямоугольную область приемника. После выполнения блиттинга BltSurface() возвращает TRUE как признак успешного завершения.