void DrawingSurface_Clear(ScriptDrawingSurface *sds, int colour) { Bitmap *ds = sds->StartDrawing(); int allegroColor; if ((colour == -SCR_NO_VALUE) || (colour == SCR_COLOR_TRANSPARENT)) { allegroColor = ds->GetMaskColor(); } else { allegroColor = ds->GetCompatibleColor(colour); } ds->Fill(allegroColor); sds->FinishedDrawing(); }
void DrawingSurface_SetDrawingColor(ScriptDrawingSurface *sds, int newColour) { sds->currentColourScript = newColour; // StartDrawing to set up ds to set the colour at the appropriate // depth for the background Bitmap *ds = sds->StartDrawing(); if (newColour == SCR_COLOR_TRANSPARENT) { sds->currentColour = ds->GetMaskColor(); } else { sds->currentColour = ds->GetCompatibleColor(newColour); } sds->FinishedDrawingReadOnly(); }
void DynamicSprite_Rotate(ScriptDynamicSprite *sds, int angle, int width, int height) { if ((angle < 1) || (angle > 359)) quit("!DynamicSprite.Rotate: invalid angle (must be 1-359)"); if (sds->slot == 0) quit("!DynamicSprite.Rotate: sprite has been deleted"); if ((width == SCR_NO_VALUE) || (height == SCR_NO_VALUE)) { // calculate the new image size automatically // 1 degree = 181 degrees in terms of x/y size, so % 180 int useAngle = angle % 180; // and 0..90 is the same as 180..90 if (useAngle > 90) useAngle = 180 - useAngle; // useAngle is now between 0 and 90 (otherwise the sin/cos stuff doesn't work) double angleInRadians = (double)useAngle * (M_PI / 180.0); double sinVal = sin(angleInRadians); double cosVal = cos(angleInRadians); width = (cosVal * (double)spritewidth[sds->slot] + sinVal * (double)spriteheight[sds->slot]); height = (sinVal * (double)spritewidth[sds->slot] + cosVal * (double)spriteheight[sds->slot]); } else { multiply_up_coordinates(&width, &height); } // convert to allegro angle angle = (angle * 256) / 360; // resize the sprite to the requested size Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, spriteset[sds->slot]->GetColorDepth()); newPic->Clear(newPic->GetMaskColor()); // rotate the sprite about its centre // (+ width%2 fixes one pixel offset problem) newPic->RotateBlt(spriteset[sds->slot], width / 2 + width % 2, height / 2, spritewidth[sds->slot] / 2, spriteheight[sds->slot] / 2, itofix(angle)); delete spriteset[sds->slot]; // replace the bitmap in the sprite set add_dynamic_sprite(sds->slot, newPic, (game.spriteflags[sds->slot] & SPF_ALPHACHANNEL) != 0); }
void update_walk_behind_images() { int ee, rr; int bpp = (thisroom.ebscene[play.bg_frame]->GetColorDepth() + 7) / 8; Bitmap *wbbmp; for (ee = 1; ee < MAX_OBJ; ee++) { update_polled_stuff_if_runtime(); if (walkBehindRight[ee] > 0) { wbbmp = BitmapHelper::CreateBitmap( (walkBehindRight[ee] - walkBehindLeft[ee]) + 1, (walkBehindBottom[ee] - walkBehindTop[ee]) + 1, thisroom.ebscene[play.bg_frame]->GetColorDepth()); wbbmp->Clear(wbbmp->GetMaskColor()); int yy, startX = walkBehindLeft[ee], startY = walkBehindTop[ee]; for (rr = startX; rr <= walkBehindRight[ee]; rr++) { for (yy = startY; yy <= walkBehindBottom[ee]; yy++) { if (thisroom.object->GetScanLine(yy)[rr] == ee) { for (int ii = 0; ii < bpp; ii++) wbbmp->GetScanLineForWriting(yy - startY)[(rr - startX) * bpp + ii] = thisroom.ebscene[play.bg_frame]->GetScanLine(yy)[rr * bpp + ii]; } } } update_polled_stuff_if_runtime(); if (walkBehindBitmap[ee] != NULL) { gfxDriver->DestroyDDB(walkBehindBitmap[ee]); } walkBehindBitmap[ee] = gfxDriver->CreateDDBFromBitmap(wbbmp, false); delete wbbmp; } } walkBehindsCachedForBgNum = play.bg_frame; }
void DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite *sds, int width, int height, int x, int y) { if (sds->slot == 0) quit("!DynamicSprite.ChangeCanvasSize: sprite has been deleted"); if ((width < 1) || (height < 1)) quit("!DynamicSprite.ChangeCanvasSize: new size is too small"); multiply_up_coordinates(&x, &y); multiply_up_coordinates(&width, &height); Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, spriteset[sds->slot]->GetColorDepth()); newPic->Clear(newPic->GetMaskColor()); // blit it into the enlarged image newPic->Blit(spriteset[sds->slot], 0, 0, x, y, spritewidth[sds->slot], spriteheight[sds->slot]); delete spriteset[sds->slot]; // replace the bitmap in the sprite set add_dynamic_sprite(sds->slot, newPic, (game.spriteflags[sds->slot] & SPF_ALPHACHANNEL) != 0); }
ScriptDynamicSprite* DynamicSprite_Create(int width, int height, int alphaChannel) { multiply_up_coordinates(&width, &height); int gotSlot = spriteset.findFreeSlot(); if (gotSlot <= 0) return NULL; Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, final_col_dep); if (newPic == NULL) return NULL; newPic->Clear(newPic->GetMaskColor()); if ((alphaChannel) && (final_col_dep < 32)) alphaChannel = false; add_dynamic_sprite(gotSlot, gfxDriver->ConvertBitmapToSupportedColourDepth(newPic), alphaChannel != 0); ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot); GlobalReturnValue.SetDynamicObject(new_spr, new_spr); return new_spr; }
void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction) { if ((direction < 1) || (direction > 3)) quit("!DynamicSprite.Flip: invalid direction"); if (sds->slot == 0) quit("!DynamicSprite.Flip: sprite has been deleted"); // resize the sprite to the requested size Bitmap *newPic = BitmapHelper::CreateBitmap(spritewidth[sds->slot], spriteheight[sds->slot], spriteset[sds->slot]->GetColorDepth()); newPic->Clear(newPic->GetMaskColor()); if (direction == 1) newPic->FlipBlt(spriteset[sds->slot], 0, 0, Common::kBitmap_HFlip); else if (direction == 2) newPic->FlipBlt(spriteset[sds->slot], 0, 0, Common::kBitmap_VFlip); else if (direction == 3) newPic->FlipBlt(spriteset[sds->slot], 0, 0, Common::kBitmap_HVFlip); delete spriteset[sds->slot]; // replace the bitmap in the sprite set add_dynamic_sprite(sds->slot, newPic, (game.spriteflags[sds->slot] & SPF_ALPHACHANNEL) != 0); }
int DrawingSurface_GetPixel(ScriptDrawingSurface *sds, int x, int y) { sds->MultiplyCoordinates(&x, &y); Bitmap *ds = sds->StartDrawing(); unsigned int rawPixel = ds->GetPixel(x, y); unsigned int maskColor = ds->GetMaskColor(); int colDepth = ds->GetColorDepth(); if (rawPixel == maskColor) { rawPixel = SCR_COLOR_TRANSPARENT; } else if (colDepth > 8) { int r = getr_depth(colDepth, rawPixel); int ds = getg_depth(colDepth, rawPixel); int b = getb_depth(colDepth, rawPixel); rawPixel = Game_GetColorFromRGB(r, ds, b); } sds->FinishedDrawingReadOnly(); return rawPixel; }
void DrawSpriteWithTransparency(Bitmap *ds, Bitmap *sprite, int x, int y, int alpha) { if (alpha <= 0) { // fully transparent, don't draw it at all return; } int surface_depth = ds->GetColorDepth(); int sprite_depth = sprite->GetColorDepth(); if (sprite_depth < surface_depth // CHECKME: what is the purpose of this hack and is this still relevant? #if defined(IOS_VERSION) || defined(ANDROID_VERSION) || (ds->GetBPP() < surface_depth && psp_gfx_renderer > 0) // Fix for corrupted speechbox outlines with the OGL driver #endif ) { // If sprite is lower color depth than destination surface, e.g. // 8-bit sprites drawn on 16/32-bit surfaces. if (sprite_depth == 8 && surface_depth >= 24) { // 256-col sprite -> truecolor background // this is automatically supported by allegro, no twiddling needed ds->Blit(sprite, x, y, kBitmap_Transparency); return; } // 256-col sprite -> hi-color background, or // 16-bit sprite -> 32-bit background Bitmap hctemp; hctemp.CreateCopy(sprite, surface_depth); if (sprite_depth == 8) { // only do this for 256-col -> hi-color, cos the Blit call converts // transparency for 16->32 bit color_t mask_color = hctemp.GetMaskColor(); for (int scan_y = 0; scan_y < hctemp.GetHeight(); ++scan_y) { // we know this must be 1 bpp source and 2 bpp pixel destination const uint8_t *src_scanline = sprite->GetScanLine(scan_y); uint16_t *dst_scanline = (uint16_t*)hctemp.GetScanLineForWriting(scan_y); for (int scan_x = 0; scan_x < hctemp.GetWidth(); ++scan_x) { if (src_scanline[scan_x] == 0) { dst_scanline[scan_x] = mask_color; } } } } if (alpha < 0xFF) { set_trans_blender(0, 0, 0, alpha); ds->TransBlendBlt(&hctemp, x, y); } else { ds->Blit(&hctemp, x, y, kBitmap_Transparency); } } else { if (alpha < 0xFF && surface_depth > 8 && sprite_depth > 8) { set_trans_blender(0, 0, 0, alpha); ds->TransBlendBlt(sprite, x, y); } else { ds->Blit(sprite, x, y, kBitmap_Transparency); } } }
void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSprite) { if (sds->slot == 0) quit("!DynamicSprite.CopyTransparencyMask: sprite has been deleted"); if ((spritewidth[sds->slot] != spritewidth[sourceSprite]) || (spriteheight[sds->slot] != spriteheight[sourceSprite])) { quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same size"); } Bitmap *target = spriteset[sds->slot]; Bitmap *source = spriteset[sourceSprite]; if (target->GetColorDepth() != source->GetColorDepth()) { quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same colour depth"); } // set the target's alpha channel depending on the source bool sourceHasAlpha = (game.spriteflags[sourceSprite] & SPF_ALPHACHANNEL) != 0; game.spriteflags[sds->slot] &= ~SPF_ALPHACHANNEL; if (sourceHasAlpha) { game.spriteflags[sds->slot] |= SPF_ALPHACHANNEL; } unsigned int maskColor = source->GetMaskColor(); int colDep = source->GetColorDepth(); int bytesPerPixel = (colDep + 1) / 8; unsigned short *shortPtr; unsigned int *longPtr; for (int y = 0; y < target->GetHeight(); y++) { unsigned char * sourcePixel = source->GetScanLineForWriting(y); unsigned char * targetPixel = target->GetScanLineForWriting(y); for (int x = 0; x < target->GetWidth(); x++) { shortPtr = (unsigned short*)sourcePixel; longPtr = (unsigned int*)sourcePixel; if ((colDep == 8) && (sourcePixel[0] == maskColor)) { targetPixel[0] = maskColor; } else if ((bytesPerPixel == 2) && (shortPtr[0] == maskColor)) { ((unsigned short*)targetPixel)[0] = maskColor; } else if ((bytesPerPixel == 3) && (memcmp(sourcePixel, &maskColor, 3) == 0)) { memcpy(targetPixel, sourcePixel, 3); } else if ((bytesPerPixel == 4) && (longPtr[0] == maskColor)) { ((unsigned int*)targetPixel)[0] = maskColor; } else if ((bytesPerPixel == 4) && (sourceHasAlpha)) { // the fourth byte is the alpha channel, copy it targetPixel[3] = sourcePixel[3]; } else if (bytesPerPixel == 4) { // set the alpha channel byte to opaque targetPixel[3] = 0xff; } sourcePixel += bytesPerPixel; targetPixel += bytesPerPixel; } } }