int FMultiPatchTexture::CopyPixels(FBitmap *bmp, int conversion) { int retv = -1; if (conversion == noremap0) { if (bTextual || !UseGamePalette()) conversion = normal; } for(int i = 0; i < NumParts; i++) { int ret = -1; FCopyInfo info; memset (&info, 0, sizeof(info)); info.alpha = Parts[i].Alpha; info.invalpha = BLENDUNIT - info.alpha; info.op = ECopyOp(Parts[i].op); PalEntry b = Parts[i].Blend; if (b.a == 0 && b != BLEND_NONE) { info.blend = EBlend(b.d); } else if (b.a != 0) { if (b.a == 255) { info.blendcolor[0] = b.r * BLENDUNIT / 255; info.blendcolor[1] = b.g * BLENDUNIT / 255; info.blendcolor[2] = b.b * BLENDUNIT / 255; info.blend = BLEND_MODULATE; } else { blend_t blendalpha = b.a * BLENDUNIT / 255; info.blendcolor[0] = b.r * blendalpha; info.blendcolor[1] = b.g * blendalpha; info.blendcolor[2] = b.b * blendalpha; info.blendcolor[3] = FRACUNIT - blendalpha; info.blend = BLEND_OVERLAY; } } auto trans = Parts[i].Translation ? Parts[i].Translation->Palette : nullptr; FBitmap Pixels = Parts[i].Image->GetCachedBitmap(trans, conversion, &ret); bmp->Blit(Parts[i].OriginX, Parts[i].OriginY, Pixels, Pixels.GetWidth(), Pixels.GetHeight(), Parts[i].Rotate, &info); // treat -1 (i.e. unknown) as absolute. We have no idea if this may have overwritten previous info so a real check needs to be done. if (ret == -1) retv = ret; else if (retv != -1 && ret > retv) retv = ret; } return retv; }
int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { int retv = -1; if (bRedirect) { // Redirect straight to the real texture's routine. return Parts[0].Texture->CopyTrueColorPixels(bmp, x, y, rotate, inf); } if (rotate != 0 || (inf != NULL && ((inf->op != OP_OVERWRITE && inf->op != OP_COPY) || inf->blend != BLEND_NONE))) { // We are doing some sort of fancy stuff to the destination bitmap, so composite to // a temporary bitmap, and copy that. FBitmap tbmp; if (tbmp.Create(Width, Height)) { retv = MAX(retv, CopyTrueColorPixels(&tbmp, 0, 0, 0)); bmp->CopyPixelDataRGB(x, y, tbmp.GetPixels(), Width, Height, 4, tbmp.GetPitch(), rotate, CF_BGRA, inf); } return retv; } // When compositing a multipatch texture with multipatch parts, // drawing must be restricted to the actual area which is covered by this texture. FClipRect saved_cr = bmp->GetClipRect(); bmp->IntersectClipRect(x, y, Width, Height); if (inf != NULL && inf->op == OP_OVERWRITE) { bmp->Zero(); } for(int i = 0; i < NumParts; i++) { int ret = -1; FCopyInfo info; if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. memset (&info, 0, sizeof(info)); info.alpha = Parts[i].Alpha; info.invalpha = BLENDUNIT - info.alpha; info.op = ECopyOp(Parts[i].op); PalEntry b = Parts[i].Blend; if (b.a == 0 && b != BLEND_NONE) { info.blend = EBlend(b.d); } else if (b.a != 0) { if (b.a == 255) { info.blendcolor[0] = b.r * BLENDUNIT / 255; info.blendcolor[1] = b.g * BLENDUNIT / 255; info.blendcolor[2] = b.b * BLENDUNIT / 255; info.blend = BLEND_MODULATE; } else { blend_t blendalpha = b.a * BLENDUNIT / 255; info.blendcolor[0] = b.r * blendalpha; info.blendcolor[1] = b.g * blendalpha; info.blendcolor[2] = b.b * blendalpha; info.blendcolor[3] = FRACUNIT - blendalpha; info.blend = BLEND_OVERLAY; } } if (Parts[i].Translation != NULL) { // Using a translation forces downconversion to the base palette ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation->Palette, &info); } else { ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info); } // treat -1 (i.e. unknown) as absolute. We have no idea if this may have overwritten previous info so a real check needs to be done. if (ret == -1) retv = ret; else if (retv != -1 && ret > retv) retv = ret; } // Restore previous clipping rectangle. bmp->SetClipRect(saved_cr); return retv; }