Функции для работы с поверхностями


Наше приложение Bounce является очень простым, поэтому функция CreateCustom Surfaces() делает не так уж много. Реальное приложение может создавать десятки и даже сотни поверхностей. Класс DirectDrawWin содержит несколько служебных функций, которые могут пригодиться при работе с поверхностями, поэтому мы ненадолго отвлечемся от приложения Bounce и рассмотрим эти функции:

LPDIRECTDRAWSURFACE CreateSurface(LPCTSTR filename, BOOL installpalette=FALSE); LPDIRECTDRAWSURFACE CreateSurface(DWORD w, DWORD h ); BOOL LoadSurface(LPDIRECTDRAWSURFACE surf, LPCTSTR filename); BOOL ClearSurface(LPDIRECTDRAWSURFACE surf, DWORD clr, RECT* rect=0); BOOL ClearSurface( LPDIRECTDRAWSURFACE surf, DWORD r, DWORD g, DWORD b, RECT* rect=0 ); BOOL GetSurfaceDimensions( LPDIRECTDRAWSURFACE surf, DWORD& w, DWORD& h );

Первая функция нам уже знакома. Функция CreateSurface(), получая имя BMP-файла, создает новую поверхность на основании его содержимого. Кроме того, эта функция может извлекать палитру из 8-битных файлов и назначать ее поверхности. Реализация этой функции подробно рассматривается в главе 5.
Вторая функция - CreateSurface() - создает поверхность заданных размеров. Эта функция полезна в тех случаях, когда вам нужна новая поверхность, содержимое которой не связано с BMP-файлом. Данная версия CreateSurface() реализована так:

LPDIRECTDRAWSURFACE DirectDrawWin::CreateSurface( DWORD w, DWORD h ) { DWORD bytes=w*h*(displaydepth/8); DDSURFACEDESC desc; ZeroMemory( &desc, sizeof(desc) ); desc.dwSize = sizeof(desc); desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; desc.dwWidth = w; desc.dwHeight = h; desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; LPDIRECTDRAWSURFACE surf; HRESULT r=ddraw2->CreateSurface( &desc, &surf, 0 ); if (r==DD_OK) { TRACE("CreateSurface(%d,%d) created in video memory \n", w, h); return surf; } desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; r=ddraw2->CreateSurface( &desc, &surf, 0 ); if (r==DD_OK) { TRACE("CreateSurface(%d,%d) allocated in system memory \n", w, h); return surf; } TRACE("CreateSurface(%d,%d) failed\n", w, h); return 0; }

Функция ClearSurface() получает три аргумента: указатель на заполняемую поверхность; величину, присваиваемую каждому пикселю; и необязательную структуру RECT, которая определяет заполняемую область поверхности.
После проверки указателя мы подготавливаем экземпляр структуры DDBLTFX. Полю dwFillColor присваивается величина, используемая для заполнения, а сама операция осуществляется функцией Blt() интерфейса DirectDrawSurface. Флаг DDBLT_COLORFILL сообщает Blt() о том, что вместо блиттинга выполняется цветовое заполнение.
Получившаяся функция удобна, но ей не хватает универсальности. Дело в том, что величина, применяемая для заполнения поверхности, может иметь различный смысл. Например, для палитровых поверхностей она представляет собой индекс в палитре. Без предварительной проверки палитры невозможно предсказать, какой цвет будет использоваться для заполнения. Аналогичные проблемы возникают и для беспалитровых поверхностей, поскольку конкретное значение пикселя зависит от глубины и формата пикселей. Форматы пикселей особенно часто различаются в режимах High Color, поэтому заполнение поверхности конкретным цветом превращается в нетривиальную задачу.
Вторая версия ClearSurface() получает в качестве аргументов RGB-составляющие и рассчитывает по ним конкретную величину, присваиваемую пикселям поверхности. В таком варианте функция становится более универсальной, но и работает медленнее; быстродействие особенно сильно снижается для палитровых поверхностей, потому что нужный цвет приходится искать в палитре. Код этой функции будет рассмотрен в главе 5.
Нам остается рассмотреть лишь функцию GetSurfaceDimensions(), которая получает указатель на поверхность и возвращает ее ширину и высоту. Код этой функции выглядит так:

BOOL DirectDrawWin::GetSurfaceDimensions( LPDIRECTDRAWSURFACE surf, DWORD& w, DWORD& h ) { if (surf==0) return FALSE; DDSURFACEDESC desc; ZeroMemory( &desc, sizeof(desc) ); desc.dwSize=sizeof(desc); desc.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; if (surf->GetSurfaceDesc( &desc )!=DD_OK) return FALSE; w=desc.dwWidth; h=desc.dwHeight; return TRUE; }

После проверки указателя мы подготавливаем экземпляр структуры DDSURFACEDESC. Нас интересуют ширина и высота поверхности, поэтому в поле dwFlags заносятся флаги DDSD_WIDTH и DDSD_HEIGHT.
Затем мы вызываем функцию GetSurfaceDesc() интерфейса DirectDrawSurface и передаем ей указатель на структуру с описанием поверхности. Функция GetSurfaceDesc() сохраняет размеры поверхности в полях dwWidth и dwHeight. Они присваиваются переданным по ссылке переменным w и h типа DWORD, после чего функция завершается.
Все рассмотренные функции встречаются в демонстрационных программах этой книги, однако вы вовсе не обязаны пользоваться ими. Впрочем, независимо от этого вам будет полезно познакомиться с их реализацией.


- Начало - - Назад - - Вперед -