// For this generic implementation, we just call GetPixels and copy that data // to the buffer. Texture formats that can do better than paletted images // should provide their own implementation that may preserve the original // color data. Note that the buffer expects row-major data, since that's // generally more convenient for any non-Doom image formats, and it doesn't // need to be used by any of Doom's column drawing routines. void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt) { const BYTE *pix; int x, y, w, h, stride; w = GetWidth(); h = GetHeight(); switch (fmt) { case TEX_Pal: case TEX_Gray: pix = GetPixels(); stride = pitch - w; for (y = 0; y < h; ++y) { const BYTE *pix2 = pix; for (x = 0; x < w; ++x) { *buff++ = *pix2; pix2 += h; } pix++; buff += stride; } break; case TEX_RGB: { FCopyInfo inf = {OP_OVERWRITE, BLEND_NONE, {0}, 0, 0}; FBitmap bmp(buff, pitch, pitch/4, height); CopyTrueColorPixels(&bmp, 0, 0, 0, &inf); break; } default: I_Error("FTexture::FillBuffer: Unsupported format %d", fmt); } }
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; }