Стэн Трухильо - Графика для Windows средствами DirectDraw
- Название:Графика для Windows средствами DirectDraw
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стэн Трухильо - Графика для Windows средствами DirectDraw краткое содержание
Графика для Windows средствами DirectDraw - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Функция DrawScene()использует функцию DirectDrawWin::BltSurface()для копирования поверхности surf1на поверхность backsurf. Два последних аргумента BltSurface()определяют точку поверхности-приемника, куда должно быть скопировано содержимое источника. Для выполнения этой операции можно было бы воспользоваться функцией Blt()или BltFast()интерфейса DirectDrawSurface, но мы не делаем этого из-за возможного отсечения. Обратите внимание - код, определяющий положение растра, позволяет источнику выйти за пределы приемника, в результате чего может потребоваться отсечение. Мы не можем воспользоваться функцией Blt(), потому что тогда потребовалось бы присоединить к приемнику объект DirectDrawClipper, чего мы не делаем. Функция BltFast()тоже не подходит, потому что она вообще не поддерживает отсечения. Функция BltSurface()автоматически выполняет отсечение, а функции Blt()и BltFast()вызываются внутри нее.
Но перед тем, как переходить к функции BltSurface(), мы закончим рассмотрение функции DrawScene(). Она завершается вызовом функции Flip(). При этом происходит переключение страниц, и подготовленный нами кадр отображается на экране. Функция Flip()получает два аргумента: указатель на поверхность и переменную типа DWORD, предназначенную для установки флагов. Указатель на поверхность необходим лишь в нестандартных ситуациях, когда в переключении поверхностей участвует несколько вторичных буферов. Второй аргумент обычно содержит флаг DDFLIP_WAIT, показывающий, что возврат из функции должен происходить только после того, как переключение страниц завершится.
Функция 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;
}
Сначала функция BltSurface()проверяет указатели на поверхности. Если хотя бы один из них равен нулю, функция возвращает FALSE, тем самым сообщая о неудаче. Если проверка прошла успешно, два объекта CRectинициализируются в соответствии с размерами поверхностей, полученными с помощью функции DirectDrawSurface::GetSurfaceDesc().
Затем BltSurface()проверяет, что попадает ли точка назначения в границы приемника. Если координаты xи yтаковы, что копия не пересекается с поверхностью приемника, блиттинг не нужен, поэтому мы просто выходим из функции.
Если же с точкой назначения все в порядке, функция проверяет, нужно ли выполнять отсечение. Если отсечение не требуется, блит-операция для достижения максимального быстродействия выполняется функцией BltFast(). Если отсечение все же необходимо, возможно, придется пользоваться функцией Blt().
Если отсечение выполняется по правому или нижнему краю источника, функция BltFast()справится с задачей и обрежет выступающую часть копируемой области. Если же отсечение происходит по верхнему или левому краю, приходится работать с функцией Blt(), потому что BltFast()не позволяет задать прямоугольную область приемника. После выполнения блиттинга BltSurface()возвращает TRUEкак признак успешного завершения.
Наше приложение благополучно инициализируется и выводит графические данные. Теперь необходимо справиться с возможной потерей поверхностей. При рассмотрении функции DirectDrawWin::PreDrawSceneмы видели, что DirectDrawWinвызывает виртуальную функцию RestoreSurfaces(), чтобы производный класс получил возможность восстановить потерянные поверхности. Функция RestoreSurfaces()отвечает за восстановление как потерянной памяти поверхности, так и ее содержимого. Функция BounceWin::RestoreSurfaces()выглядит так:
void BounceWin::RestoreSurfaces() {
if (surf1->IsLost()==FALSE) return;
CString filename;
if (GetCurDisplayDepth()==8) filename="tri08.bmp";
else filename="tri24.bmp";
surf1->Restore();
LoadSurface(surf1, filename);
}
DirectDraw может отнимать у неактивного приложения только поверхности, находящиеся в видеопамяти, так что нет смысла в восстановлении поверхностей из системной памяти. Поэтому RestoreSurfaces()сначала проверяет, была ли потеряна единственная вспомогательная поверхность нашего приложения, и если нет — функция прекращает работу. Если же поверхность была потеряна, мы восстанавливаем ее память функцией Restore(), а содержимое — функцией LoadSurface().
Читать дальшеИнтервал:
Закладка: