BOOL CBitBuffer::CreateScreenBits( NativePlayerWnd* native, SRECT* frame) { FLASHASSERT( ( frame->xmax - frame->xmin ) > 0 ); FLASHASSERT( ( frame->ymax - frame->ymin ) > 0 ); FreeBits(); SColorTable* table = 0; int depth; // Pick a format for the offscreen bitmap depth = NativeDisplayTester::CurrentScreenBitDepth(); if ( screenDepth != depth ) { if ( screenDepth > 0 ) { delete m_cinfo; m_cinfo = 0; } // We need to profile the device screenDepth = depth; NativeDisplayTester tester; tester.TestDepth( screenDepth ); screenFormat = tester.BestDetectedFormat(); screenInverted = tester.BestDetectedInvert(); } m_inverted = screenInverted; m_xorg = 0; if ( screenFormat <= pix8 ) { if ( m_cinfo ) { delete m_cinfo; m_cinfo = 0; } SColorTable ctab; NativePalette::GetScreenPalette( &ctab ); m_cinfo = CreateColorInfo( &ctab ); if ( !m_cinfo ) return false; AttachColorInfo(m_cinfo); table = &m_cinfo->ctab; } bitmap = new NativeBitmap( native, table, frame->xmax - frame->xmin, frame->ymax - frame->ymin, screenDepth, screenFormat ); return ( bitmap->ScanLine() != 0 ); }
void ReleaseColorInfo(SColorInfo* cinfo) { if ( !cinfo ) return; FLASHASSERT( cinfo->refCount ); if ( --cinfo->refCount == 0 ) { SColorInfo** link = &firstColorInfo; if(*link) { while ( *link ) { if ( *link == cinfo ) { *link = cinfo->next; cinfo->DestroyOSPalette(); memset( cinfo, 0, sizeof( SColorInfo ) ); delete cinfo; return; } link = &cinfo->next; } } else { cinfo->DestroyOSPalette(); delete cinfo; return; } } }
void DisplayList::RemoveThread(ScriptThread* thread) { // Clear any pending actions on a thread that is going away actionList.RemoveThread(thread); // If we are inside a DoActions, remove pending actions on // the action context stack ActionContext* actionContext = actionCallStack; for (int i=0; i<actionCallStackTop; i++) { if (actionContext->targetThread == thread) { actionContext->targetThread = 0; actionContext->useTarget = false; } actionContext->actionList->RemoveThread(thread); actionContext++; } // Remove the thread from the list ScriptThread** link = &threads; while ( *link ) { if ( *link == thread ) { *link = thread->next; return; } link = &(*link)->next; } FLASHASSERT(false); }
BOOL NativePlayerWnd::StartTimer( int playTimerInterval, int cursorTimerInterval ) { if ( !loaded ) return false; FLASHASSERT( playTimerInterval ); FLASHASSERT( cursorTimerInterval ); flash->cursorTimeInterval=cursorTimerInterval; flash->cursorTime=GetTickCount(); playTimer = flash->timer(playTimerInterval); //SetTimer( hwnd, TIMER_PLAY, playTimerInterval, 0 ); //cursorTimer = SetTimer( hwnd, TIMER_CURSOR, cursorTimerInterval, 0 ); return true; }
void DecomposeRect(SRECT* r1, SRECT* r2) // Restructure two overlaping rectangles to eliminate the intersecting area // while still covering the same area and perhaps more area { FLASHASSERT(RectTestOverlap(r1, r2)); // Build the 3 rect slabs on y-axis SRECT r[3]; if ( r1->ymin < r2->ymin ) { r[0].ymin = r1->ymin; r[0].ymax = r2->ymin; r[0].xmin = r1->xmin; r[0].xmax = r1->xmax; } else { r[0].ymin = r2->ymin; r[0].ymax = r1->ymin; r[0].xmin = r2->xmin; r[0].xmax = r2->xmax; } if ( r1->ymax < r2->ymax ) { r[2].ymin = r1->ymax; r[2].ymax = r2->ymax; r[2].xmin = r2->xmin; r[2].xmax = r2->xmax; } else { r[2].ymin = r2->ymax; r[2].ymax = r1->ymax; r[2].xmin = r1->xmin; r[2].xmax = r1->xmax; } r[1].ymin = r[0].ymax; r[1].ymax = r[2].ymin; r[1].xmin = Min(r1->xmin, r2->xmin); r[1].xmax = Max(r1->xmax, r2->xmax); // Combine the middle slab with the slab that will generate the smallest area S32 a[3]; for ( int i = 0; i < 3; i++ ) a[i] = RectArea(r+i); SRECT u1, u2; RectUnion(&r[0], &r[1], &u1); RectUnion(&r[1], &r[2], &u2); S32 delta0 = a[0] + a[1] - RectArea(&u1); S32 delta1 = a[1] + a[2] - RectArea(&u2); if ( delta0 > delta1 ) { *r1 = u1; *r2 = r[2]; } else { *r1 = r[0]; *r2 = u2; } }
void DisplayList::DoButtonStateTransition(SObject* newButton, int transition) { FLASHASSERT(newButton); switch ( transition ) { case bsIdleToOverUp: case bsOverDownToOverUp: buttonState = bsOverUp; break; case bsOverUpToIdle: case bsOutDownToIdle: case bsOverDownToIdle: buttonState = bsIdle; break; case bsOverUpToOverDown: case bsOutDownToOverDown: case bsIdleToOverDown: buttonState = bsOverDown; break; case bsOverDownToOutDown: buttonState = bsOutDown; break; default: FLASHASSERT(false); } UpdateButton(newButton, buttonState); DoButtonAction(newButton, transition); if ( buttonState == bsIdle ) { button = 0; buttonParent = 0; buttonCharacter = 0; buttonDepth = 0; buttonRatio = 0; } else { button = newButton; buttonParent = newButton->parent; buttonCharacter = newButton->character; buttonDepth = newButton->depth; buttonRatio = newButton->ratio; } }
SObject* DisplayList::MoveObject(SObject* parent, PlaceInfo* info) { // See if there is already an object at this depth or find the insertion point SObject* obj = parent->bottomChild; while ( obj ) { if ( obj->depth >= info->depth ) break; obj = obj->above; } if ( obj ) { // We found an object at this depth if ( obj->depth != info->depth ) { FLASHASSERT(false); return 0; // don't move the wrong object } if (obj->puppet) return 0; // don't move the object if it's puppeted // Move the proper fields of the object obj->Modify(); if ( info->flags & splaceCharacter ) { // The type of sprite or button objects must never change if ( obj->character->type != info->character->type && (obj->character->type == spriteChar || info->character->type == spriteChar || obj->character->type == buttonChar || info->character->type == buttonChar) ) { FLASHASSERT(false); // this should never happen, there was a beta build where we did export like this, so prevent the crash } else { obj->character = info->character; } } if ( info->flags & splaceMatrix ) obj->xform.mat = info->mat; if ( info->flags & splaceColorTransform ) obj->xform.cxform = info->cxform; if ( info->flags & splaceRatio ) obj->ratio = info->ratio; } return obj; }
void NativeSoundMix::BuildAndWrite( WaveHeader* wave, BOOL silence ) { int i = wave->bufferId; WAVEHDR* hdr = &waveHDR[i]; // Clean up the header int res = waveOutUnprepareHeader(hWaveOut, hdr, sizeof(WAVEHDR)); FLASHASSERT(res == MMSYSERR_NOERROR); // Generate the sound info if ( silence ) { memset(buffer[i], mixFormat.Is8Bit() ? 0x80 : 0, bufferBytes); } else { BuildBuffer( i ); } res = waveOutPrepareHeader(hWaveOut, hdr, sizeof(WAVEHDR)); FLASHASSERT(res == MMSYSERR_NOERROR); res = waveOutWrite(hWaveOut, hdr, sizeof(WAVEHDR)); FLASHASSERT(res == MMSYSERR_NOERROR); }
void NativeSoundMix::CloseNativeDevice() { if ( !isOpen ) return; SetEvent(playEvent); // signal the thread to quit EnterCritical(); // do this after we kill the timer proc to prevent a deadlock if ( !isOpen ) { LeaveCritical(); return; // It is possible for timeKillEvent to call CloseDevice } isOpen = false; HWAVEOUT hW = hWaveOut; hWaveOut = 0; // flag that we are shutting down so PollSound will bail int res = waveOutReset(hW); FLASHASSERT(res == MMSYSERR_NOERROR); for ( int i = 0; i < nBuffers; i++ ) { int limit = 50; while ( limit-- ) { int res = waveOutUnprepareHeader(hW, waveHDR+i, sizeof(WAVEHDR)); if ( res != WAVERR_STILLPLAYING ) { FLASHASSERT(res == MMSYSERR_NOERROR); break; } Sleep(1); } } res = waveOutClose(hW); FLASHASSERT(res == MMSYSERR_NOERROR); CloseHandle(playThread); playThread = 0; LeaveCritical(); }
int NativeDisplayTester::DepthToSimplestPixelFormat( int depth ) { int pixelFormat; switch ( depth ) { case 1: pixelFormat = pix1; break; case 4: pixelFormat = pix4; break; case 8: pixelFormat = pix8; break; case 16: pixelFormat = pix16; break; case 24: pixelFormat = pix24; break; case 32: pixelFormat = pix32; break; default: FLASHASSERT(false); } return pixelFormat; }
void DisplayList::DoRemove(SObject** link) { SObject* obj = *link; FLASHASSERT(obj); // Remove the contents of the old object if ( obj->drawn ) InvalidateRect(&obj->devBounds); obj->FreeChildren(); obj->Free(); // Remove from list if ( obj == button ) button = 0; *link = obj->above; FreeObject(obj); }
SColorInfo* GetColorInfo(SColorTable* ctab) { // Find an existing color table SColorInfo* cinfo = firstColorInfo; while ( cinfo ) { FLASHASSERT( cinfo->refCount ); if ( ColorTableEqual(ctab, &cinfo->ctab) ) { cinfo->refCount++; return cinfo; } cinfo = cinfo->next; } // Create a new inverse table cinfo = CreateColorInfo(ctab); if ( !cinfo ) return 0; cinfo->next = firstColorInfo; firstColorInfo = cinfo; return cinfo; }
void DisplayList::InvalidateRect(SRECT* r) { SRECT rect; rect.xmin = r->xmin; rect.xmax = r->xmax; rect.ymin = r->ymin; rect.ymax = r->ymax; RectInset(antialias ? -8 : -2, &rect); if ( RectTestIntersect(&devViewRect, &rect) ) { FLASHASSERT(nDirty < maxDirtyAreas); // Add to the list RectIntersect(&devViewRect, &rect, &devDirtyRect[nDirty]); RectUnion(&devDirtyRgn, &devDirtyRect[nDirty], &devDirtyRgn); // add to the dirty region devDirtyArea[nDirty] = RectArea(devDirtyRect+nDirty); // add to the list nDirty++; MergeDirtyList(nDirty == maxDirtyAreas); } }
void DisplayList::SetCamera(SRECT* frame, SRECT* viewRct, BOOL smooth, int scaleMode) { // Set up the camera SRECT viewPort = *viewRct; if ( smooth ) { viewPort.xmin *= 4; viewPort.ymin *= 4; viewPort.xmax *= 4; viewPort.ymax *= 4; } // Calculate the mapping // src = frame // dst = viewPort MATRIX newMat; #define minMapSize 0x10L FLASHASSERT(!RectIsEmpty(&viewPort) && !RectIsEmpty(frame)); newMat.a = FixedDiv(FixedMax(RectWidth(&viewPort), minMapSize), FixedMax(RectWidth(frame), minMapSize)); newMat.d = FixedDiv(FixedMax(RectHeight(&viewPort), minMapSize), FixedMax(RectHeight(frame), minMapSize)); newMat.b = newMat.c = 0; // Adjust the scaling to maintain the aspect ratio switch ( scaleMode & scaleMask ) { case showAll: newMat.a = newMat.d = FixedMin(newMat.a, newMat.d); break; case noBorder: newMat.a = newMat.d = FixedMax(newMat.a, newMat.d); break; case exactFit: //MatrixMap(frame, &viewPort, &newMat); break; case noScale: newMat.a = newMat.d = smooth ? 4*fixed_1/20 : fixed_1/20; break; } // Pick the alignment point SPOINT srcRef, dstRef; if ( scaleMode & alignLeft ) { srcRef.x = frame->xmin; dstRef.x = viewPort.xmin; } else if ( scaleMode & alignRight ) { srcRef.x = frame->xmax; dstRef.x = viewPort.xmax; } else { srcRef.x = FixedAverage(frame->xmin, frame->xmax); dstRef.x = FixedAverage(viewPort.xmin, viewPort.xmax); } if ( scaleMode & alignTop ) { srcRef.y = frame->ymin; dstRef.y = viewPort.ymin; } else if ( scaleMode & alignBottom ) { srcRef.y = frame->ymax; dstRef.y = viewPort.ymax; } else { srcRef.y = FixedAverage(frame->ymin, frame->ymax); dstRef.y = FixedAverage(viewPort.ymin, viewPort.ymax); } // Calculate the translation based on the alignment newMat.tx = dstRef.x - FixedMul(srcRef.x, newMat.a); newMat.ty = dstRef.y - FixedMul(srcRef.y, newMat.d); // Don't invalidate unless there was a change BOOL smoothBits = smooth && !faster; if ( newMat.a != camera.mat.a || newMat.b != camera.mat.b || newMat.c != camera.mat.c || newMat.d != camera.mat.d || newMat.tx != camera.mat.tx || newMat.ty != camera.mat.ty || antialias != smooth || raster.smoothBitmaps != smoothBits ) { antialias = smooth; camera.mat = newMat; raster.smoothBitmaps = smoothBits; raster.bitmapDither = antialias ? errorDiffusionDither : orderedDither; ModifyCamera(); } }
void DisplayList::DoButtonAction(SObject* target, int transition) { SCharacter* ch = target->character; FLASHASSERT(ch->type == buttonChar); if ( ch->tagCode == stagDefineButton2 ) { // Handle the new style button SParser parser; parser.Attach(ch->data, 0); BOOL first = true; for (;;) { S32 link = parser.pos; int offset = parser.GetWord(); if ( !first ) { int code = parser.GetWord(); if ( code & (1<<transition) ) { PushAction(parser.script+parser.pos, target->thread); } } if ( !offset ) break; parser.pos = link + offset; first = false; } } else { // Handle the old style button if ( transition == bsOverDownToOverUp ) { // Do the button action on the mouse up in SParser parser; parser.Attach(ch->data, 0); // Skip over the child data for (;;) { U8 stateFlags = parser.GetByte(); if ( !stateFlags ) break; MATRIX m; parser.SkipBytes(4);//GetWord(); //parser.GetWord(); parser.GetMatrix(&m); } // Handle the action PushAction(parser.script+parser.pos, target->thread); } } #ifdef SOUND {// Play the sound int state = 0; switch ( transition ) { case bsIdleToOverDown: case bsIdleToOverUp: state = sbtnOverState; break; case bsOverUpToOverDown: state = sbtnDownState; break; case bsOverDownToOverUp: state = sbtnHitTestState; break; case bsOverUpToIdle: case bsOutDownToIdle: case bsOverDownToIdle: state = sbtnUpState; break; } if ( state && ch->button.soundData ) { SParser parser; parser.Attach(ch->button.soundData, 0); // Skip the sounds for ( int i = 1; i < state; i <<= 1 ) { U16 tag = parser.GetWord(); if ( tag ) parser.GetSoundInfo(0);// skip the data } // Get the sound we want U16 tag = parser.GetWord(); if ( tag ) { SCharacter* sound = ch->player->FindCharacter(tag); if ( !sound || sound->type != soundChar ) return; CSoundChannel* channel = new CSoundChannel(); if ( channel ) { channel->AddRef(); channel->sound = &sound->sound; channel->tag = (U32)this; parser.GetSoundInfo(channel); // set up envelope, inPoint, loops, etc... theSoundMix->AddSound(channel); channel->Release(); } } } } #endif }
void DisplayList::AddThread(ScriptThread* thread) { FLASHASSERT(!thread->next); thread->next = threads; threads = thread; }
BOOL DisplayList::SetButton(SObject* newButton, BOOL mouseIsDown) { FLASHASSERT(!newButton || newButton->character->type == buttonChar); if ( !button ) { // just in case the button was removed buttonState = bsIdle; buttonParent = 0; buttonCharacter = 0; buttonDepth = 0; buttonRatio = 0; } BOOL changed = false; switch ( buttonState ) { case bsIdle: { FLASHASSERT(!button); if ( newButton ) { if ( !mouseIsDown ) { // The mouse has come over the button DoButtonStateTransition(newButton, bsIdleToOverUp); changed = true; } else if ( newButton->character->button.trackAsMenu ) { // Enter a button while the mouse is down DoButtonStateTransition(newButton, bsIdleToOverDown); changed = true; } } } break; case bsOverUp: { FLASHASSERT(button); if ( button == newButton ) { if ( mouseIsDown ) { // The mouse clicked on the button DoButtonStateTransition(button, bsOverUpToOverDown); changed = true; } } else { // The mouse is over a different button DoButtonStateTransition(button, bsOverUpToIdle); changed = true; } } break; case bsOverDown: { FLASHASSERT(button); if ( button == newButton ) { if ( !mouseIsDown ) { // The mouse was released over the button DoButtonStateTransition(button, bsOverDownToOverUp); changed = true; } } else { if ( button->character->button.trackAsMenu ) { // Exit the button DoButtonStateTransition(button, bsOverDownToIdle); changed = true; } else { // The mouse is over a different button DoButtonStateTransition(button, bsOverDownToOutDown); changed = true; } } } break; case bsOutDown: { FLASHASSERT(button); if ( button == newButton ) { // The mouse went back over the button DoButtonStateTransition(button, bsOutDownToOverDown); changed = true; } else if ( !mouseIsDown ) { // The mouse was released outside the button DoButtonStateTransition(button, bsOutDownToIdle); changed = true; } } break; } // If we deactivated a button, we may need to activate a new button if ( changed && !button && newButton ) SetButton(newButton, mouseIsDown); // call again return changed; }
void DisplayList::FinishHold() // Compare the old and the new list // If an old object matches a new object, replace the new object with the old object { FLASHASSERT(holdParent); SObject** oldLink = &holdList; SObject** newLink = &holdParent->bottomChild; for (;;) { SObject* oldObj = *oldLink; SObject* newObj = *newLink; if ( !oldObj ) break; // we are done if ( !newObj || oldObj->depth < newObj->depth ) { if ( oldObj->depth >= 0x4000 ) { // This is a cloned object, it always gets copied to the new list FLASHASSERT(!newObj); // none of the new obj's should have a depth > 4000 *oldLink = oldObj->above; // remove from old list oldObj->above = *newLink; // place on new list *newLink = oldObj; } else { // Get rid of the old object DoRemove(oldLink); } } else if ( oldObj->depth == newObj->depth ) { // Compare these objects BOOL remove = true; if (oldObj->character == newObj->character && oldObj->ratio == newObj->ratio && oldObj->clipDepth == newObj->clipDepth) { // Check the matrix and cxform and ratio BOOL moved = !Equal(&oldObj->xform, &newObj->xform); if (!moved || oldObj->character->type == spriteChar) { if ( moved && !oldObj->puppet) { oldObj->Modify(); oldObj->xform = newObj->xform; //oldObj->ratio = newObj->ratio; } if ( button == newObj ) { FLASHASSERT(oldObj->state == buttonState); button = oldObj; //UpdateButton(obj, state); } remove = false; } } else if ( oldObj->ratio == newObj->ratio && (oldObj->character->type == spriteExternalChar || oldObj->character->type == spriteChar) && (newObj->character->type == spriteChar || newObj->character->type == spriteExternalChar)) { // we are dealing with externally loaded sprite // or an empty placeholder. It inherits the // sprite ratio of the sprite we are replacing. // This means that it goes away when the same // time the replaced sprite should have gone away if (!Equal(&oldObj->xform, &newObj->xform)) { if (!oldObj->puppet) { oldObj->Modify(); oldObj->xform = newObj->xform; } } remove = false; } if (!remove) { DoRemove(newLink); // delete the new obj *oldLink = oldObj->above; // remove from old list oldObj->above = *newLink; // place on new list *newLink = oldObj; continue; } newLink = &newObj->above; DoRemove(oldLink); } else { // Just look at the next new object FLASHASSERT(oldObj->depth > newObj->depth); newLink = &newObj->above; } } #ifdef EDITTEXT // Update edit texts on hold list SObject* obj = holdParent->bottomChild; while (obj) { if (obj->character && obj->character->type == editTextChar) { obj->editText->UpdateFromVariable(); } obj = obj->above; } #endif holdParent = 0; }
SObject* DisplayList::PlaceObject(SObject* parent, PlaceInfo* info) { // Find the insertion point SObject** link = &parent->bottomChild; for (;;) { SObject* obj = *link; if ( !obj ) break; if ( obj->depth >= info->depth ) { FLASHASSERT(obj->depth != info->depth); break; } link = &obj->above; } // Create a new object SObject* obj = CreateObject(); if ( !obj ) return 0; // Add to list obj->parent = parent; obj->above = *link; *link = obj; // Set up object obj->character = info->character; obj->xform = *info; obj->depth = info->depth; obj->ratio = info->ratio; obj->puppet = info->puppet; obj->drawn = false; obj->visible = true; obj->dragCenter = false; RectSetEmpty(&obj->dragConstraint); obj->dropTarget = NULL; obj->display = this; obj->bottomChild = 0; obj->edges = 0; obj->colors = 0; obj->state = 0; #ifdef EDITTEXT obj->editText = 0; #endif // If this is a movie clip and it has no name, // generate a default name if (obj->character->type == spriteChar && !info->name) { URLBuilder ub; ub.AppendString("instance"); ub.AppendInt(++instanceNameCount); obj->name = CreateStr(ub.buf); } else { // Regular processing: copy name if present obj->name = CreateStr(info->name); } obj->thread = parent ? parent->thread : 0; obj->clipDepth = info->flags & splaceDefineClip ? info->clipDepth : 0;//(info->flags & splaceDefineClip) != 0; obj->Modify(); switch ( obj->character->type ) { case buttonChar: { // Set up the button state int state = bsIdle; if ( obj->depth == buttonDepth && obj->parent == buttonParent && buttonCharacter == obj->character && obj->ratio == buttonRatio ) { // The button is currently being tracked FLASHASSERT(obj->character->type == buttonChar); button = obj; state = buttonState; } UpdateButton(obj, state); } break; #ifdef EDITTEXT case editTextChar: { obj->editText = new EditText(obj); if (holdParent != obj->parent) { // Not doing a hold... update value immediately obj->editText->UpdateFromVariable(); } // If there is a holdParent, the edit text's value will // be updated later. } break; #endif case spriteExternalChar: { ScriptThread *thread = 0; ScriptPlayer *player = obj->character->player; int startPos = 0; int len = 0; int numFrames = 0; if (info->flags & splaceCloneExternalSprite) { // means we are cloning an existing // external sprite if (player->len >= player->scriptLen) { // we only clone the external // sprite if it has been completely loaded // allocate full player instead of thread // it is easier to delete the external // sprite if it has its own player thread = new ScriptPlayer; startPos = player->startPos; len = player->len; numFrames = player->numFrames; thread->script = player->script; ((ScriptPlayer *) thread)->numFramesComplete = player->numFramesComplete; player = (ScriptPlayer *) thread; player->gotHeader = true; // add a ref count to the script // we don't want to duplicate it // so we want to make sure it's // protected from deletion for // cloned external sprites player->scriptRefCount = obj->character->player->scriptRefCount; player->ScriptAddRefCount(); } } else { // note that it's ok to have some of the // initial values of the len, etc. set // to zero. they will be set during pushdata thread = player; // add a ref count to the script // we don't want to duplicate it // so we want to make sure it's // protected from deletion for // cloned external sprites player->ScriptAddRefCount(); } if ( thread ) { thread->ClearState(); obj->thread = thread; thread->player = player; thread->layerDepth = obj->depth; thread->rootObject = obj; thread->SetDisplay(obj->display); thread->Attach(obj->character->player->script, startPos); thread->len = len; thread->startPos = startPos; thread->numFrames = numFrames; // for non cloned sprite this won't draw the frame // untill we push data into the script (this is ok) thread->DrawFrame(0, false); } } break; case spriteChar: { // Create a sprite thread ScriptThread* thread = new ScriptThread(); if ( thread ) { thread->ClearState(); obj->thread = thread; thread->player = obj->character->player; thread->layerDepth = obj->depth; thread->rootObject = obj; thread->SetDisplay(obj->display); thread->Attach(obj->character->data, 0); thread->len = obj->character->sprite.length; thread->startPos = 0; thread->numFrames = obj->character->sprite.numFrames; thread->DrawFrame(0, false); } } break; } return obj; }
NativeBitmap::NativeBitmap( NativePlayerWnd* native, const SColorTable* table, int _width, int _height, int _depth, int _pixelFormat ) { U32 nColors; LOGPALETTE256 logpal = { 0x300, 256 }; FLASHOUTPUT( "NativeBitmap created\n" ); width = ( _width + 3 ) & ( ~0x03 ); // increase the width to be byte-aligned height = _height; depth = _depth; format = _pixelFormat; nColors = NativeDisplayTester::CurrentScreenColors(); bytesPerLine = ( width * depth + 7 ) / 8; if ( depth < 8 ) { FLASHASSERT( 0 ); // not supported in this version.... } else if ( depth == 8 ) { for ( U32 i=0; i<nColors; i++ ) { logpal.palEntry[i].peRed = info.bmiColors[i].rgbRed = table->colors[i].red; logpal.palEntry[i].peGreen = info.bmiColors[i].rgbGreen = table->colors[i].green; logpal.palEntry[i].peBlue = info.bmiColors[i].rgbBlue = table->colors[i].blue; info.bmiColors[i].rgbReserved = 0; if ( i >= 10 && i < 246 ) logpal.palEntry[i].peFlags = PC_NOCOLLAPSE; else logpal.palEntry[i].peFlags = 0; } // Create a Palette object palette = ::CreatePalette((LOGPALETTE *)&logpal); } else { nColors = 0; palette = 0; } memset( &info.bmiHeader, 0, sizeof( BITMAPINFOHEADER ) ); info.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); // + nColors * sizeof( RGBQUAD ); info.bmiHeader.biWidth = width; info.bmiHeader.biHeight = height; info.bmiHeader.biPlanes = 1; // Must be 1. Thank you windows. info.bmiHeader.biBitCount = depth; info.bmiHeader.biCompression = BI_RGB; info.bmiHeader.biSizeImage = height * bytesPerLine; info.bmiHeader.biClrUsed = nColors; info.bmiHeader.biClrImportant = nColors; HDC hdc = native->GetNWindowDC(); hBitmap = CreateDIBSection( hdc, (BITMAPINFO*) &info, DIB_RGB_COLORS, (void**) &bits, 0, 0); // HBITMAP hbmOld = (HBITMAP)::SelectObject(hdc, hBitmap); native->ReleaseWindowDC(); FLASHASSERT( hBitmap ); }