173a2ffbaSStephan Aßmus /* 273a2ffbaSStephan Aßmus * Copyright 2006, Haiku. All rights reserved. 373a2ffbaSStephan Aßmus * Distributed under the terms of the MIT License. 473a2ffbaSStephan Aßmus * 573a2ffbaSStephan Aßmus * Authors: 673a2ffbaSStephan Aßmus * Stephan Aßmus <superstippi@gmx.de> 773a2ffbaSStephan Aßmus */ 873a2ffbaSStephan Aßmus 936947c7bSOliver Tappe 1073a2ffbaSStephan Aßmus #include "Layer.h" 1173a2ffbaSStephan Aßmus 1273a2ffbaSStephan Aßmus #include <stdio.h> 1373a2ffbaSStephan Aßmus 1473a2ffbaSStephan Aßmus #include <Bitmap.h> 15*6537cf97SJérôme Duval #include <Catalog.h> 1673a2ffbaSStephan Aßmus #include <Message.h> 1773a2ffbaSStephan Aßmus 1873a2ffbaSStephan Aßmus #include "bitmap_compression.h" 1973a2ffbaSStephan Aßmus #include "blending.h" 2073a2ffbaSStephan Aßmus #include "lab_convert.h" 2173a2ffbaSStephan Aßmus #include "support.h" 2273a2ffbaSStephan Aßmus 2336947c7bSOliver Tappe 24*6537cf97SJérôme Duval #undef B_TRANSLATE_CONTEXT 25*6537cf97SJérôme Duval #define B_TRANSLATE_CONTEXT "Layer" 26*6537cf97SJérôme Duval 27*6537cf97SJérôme Duval 2873a2ffbaSStephan Aßmus // constructor 2973a2ffbaSStephan Aßmus Layer::Layer() 3073a2ffbaSStephan Aßmus : fBitmap(NULL), 3173a2ffbaSStephan Aßmus fBounds(0.0, 0.0, -1.0, -1.0), 3273a2ffbaSStephan Aßmus fAlpha(1.0), 3373a2ffbaSStephan Aßmus fMode(MODE_NORMAL), 3473a2ffbaSStephan Aßmus fFlags(0) 3573a2ffbaSStephan Aßmus { 3673a2ffbaSStephan Aßmus } 3773a2ffbaSStephan Aßmus 3836947c7bSOliver Tappe 3973a2ffbaSStephan Aßmus // destructor 4073a2ffbaSStephan Aßmus Layer::~Layer() 4173a2ffbaSStephan Aßmus { 4273a2ffbaSStephan Aßmus delete fBitmap; 4373a2ffbaSStephan Aßmus } 4473a2ffbaSStephan Aßmus 4536947c7bSOliver Tappe 4673a2ffbaSStephan Aßmus // Compose 4773a2ffbaSStephan Aßmus status_t 4873a2ffbaSStephan Aßmus Layer::Compose(const BBitmap* into, BRect area) 4973a2ffbaSStephan Aßmus { 5073a2ffbaSStephan Aßmus if (!fBitmap || !fBitmap->IsValid() 5136947c7bSOliver Tappe || (fBitmap->ColorSpace() != B_RGBA32 5236947c7bSOliver Tappe && fBitmap->ColorSpace() != B_RGB32)) 5373a2ffbaSStephan Aßmus return B_NO_INIT; 5473a2ffbaSStephan Aßmus 5573a2ffbaSStephan Aßmus status_t status = B_BAD_VALUE; 5673a2ffbaSStephan Aßmus if (!into || !area.IsValid() || (status = into->InitCheck()) < B_OK) 5773a2ffbaSStephan Aßmus return status; 5873a2ffbaSStephan Aßmus 5973a2ffbaSStephan Aßmus // make sure we don't access memory outside of our bitmap 6073a2ffbaSStephan Aßmus area = area & fBitmap->Bounds(); 6173a2ffbaSStephan Aßmus 6273a2ffbaSStephan Aßmus BRect r = ActiveBounds(); 6373a2ffbaSStephan Aßmus if (!r.IsValid() || (fFlags & FLAG_INVISIBLE) || !r.Intersects(area)) 6473a2ffbaSStephan Aßmus return B_OK; 6573a2ffbaSStephan Aßmus 6673a2ffbaSStephan Aßmus r = r & area; 6773a2ffbaSStephan Aßmus int32 left, top, right, bottom; 6873a2ffbaSStephan Aßmus rect_to_int(r, left, top, right, bottom); 6973a2ffbaSStephan Aßmus 7073a2ffbaSStephan Aßmus uint8* src = (uint8*)fBitmap->Bits(); 7173a2ffbaSStephan Aßmus uint8* dst = (uint8*)into->Bits(); 7273a2ffbaSStephan Aßmus uint32 bpr = into->BytesPerRow(); 7373a2ffbaSStephan Aßmus src += 4 * left + bpr * top; 7473a2ffbaSStephan Aßmus dst += 4 * left + bpr * top; 7573a2ffbaSStephan Aßmus uint8 alphaOverride = (uint8)(fAlpha * 255); 7673a2ffbaSStephan Aßmus 7773a2ffbaSStephan Aßmus switch (fMode) { 7873a2ffbaSStephan Aßmus 7973a2ffbaSStephan Aßmus case MODE_SOFT_LIGHT: 8073a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 8173a2ffbaSStephan Aßmus uint8* srcHandle = src; 8273a2ffbaSStephan Aßmus uint8* dstHandle = dst; 8373a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 8473a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 8573a2ffbaSStephan Aßmus uint8 c1 = dstHandle[0] * srcHandle[0] >> 8; 86258b762aSOliver Tappe c1 += dstHandle[0] * ( 8736947c7bSOliver Tappe 255 - ( 8836947c7bSOliver Tappe (255 - dstHandle[0]) 8936947c7bSOliver Tappe * (255 - srcHandle[0]) 9036947c7bSOliver Tappe >> 8 9136947c7bSOliver Tappe ) - c1 9236947c7bSOliver Tappe ) >> 8; 9336947c7bSOliver Tappe c1 = (c1 * dstHandle[3] 9436947c7bSOliver Tappe + srcHandle[0] * (255 - dstHandle[3]) 9536947c7bSOliver Tappe ) >> 8; 9673a2ffbaSStephan Aßmus 9773a2ffbaSStephan Aßmus uint8 c2 = dstHandle[1] * srcHandle[1] >> 8; 98258b762aSOliver Tappe c2 += dstHandle[1] * ( 9936947c7bSOliver Tappe 255 - ( 10036947c7bSOliver Tappe (255 - dstHandle[1]) 10136947c7bSOliver Tappe * (255 - srcHandle[1]) 10236947c7bSOliver Tappe >> 8 10336947c7bSOliver Tappe ) - c2 10436947c7bSOliver Tappe ) >> 8; 10536947c7bSOliver Tappe c2 = (c2 * dstHandle[3] 10636947c7bSOliver Tappe + srcHandle[1] * (255 - dstHandle[3]) 10736947c7bSOliver Tappe ) >> 8; 10873a2ffbaSStephan Aßmus 10973a2ffbaSStephan Aßmus uint8 c3 = dstHandle[2] * srcHandle[2] >> 8; 110258b762aSOliver Tappe c3 += dstHandle[2] * ( 11136947c7bSOliver Tappe 255 - ( 11236947c7bSOliver Tappe (255 - dstHandle[2]) 11336947c7bSOliver Tappe * (255 - srcHandle[2]) 11436947c7bSOliver Tappe >> 8 11536947c7bSOliver Tappe ) - c3 11636947c7bSOliver Tappe ) >> 8; 11736947c7bSOliver Tappe c3 = (c3 * dstHandle[3] 11836947c7bSOliver Tappe + srcHandle[2] * (255 - dstHandle[3]) 11936947c7bSOliver Tappe ) >> 8; 12073a2ffbaSStephan Aßmus 12136947c7bSOliver Tappe blend_colors(dstHandle, 12236947c7bSOliver Tappe (srcHandle[3] * alphaOverride) >> 8, c1, c2, c3); 12373a2ffbaSStephan Aßmus } 12473a2ffbaSStephan Aßmus srcHandle += 4; 12573a2ffbaSStephan Aßmus dstHandle += 4; 12673a2ffbaSStephan Aßmus } 12773a2ffbaSStephan Aßmus src += bpr; 12873a2ffbaSStephan Aßmus dst += bpr; 12973a2ffbaSStephan Aßmus } 13073a2ffbaSStephan Aßmus break; 13173a2ffbaSStephan Aßmus 13273a2ffbaSStephan Aßmus case MODE_LIGHTEN: 13373a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 13473a2ffbaSStephan Aßmus uint8* srcHandle = src; 13573a2ffbaSStephan Aßmus uint8* dstHandle = dst; 13673a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 13773a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 13873a2ffbaSStephan Aßmus // compose 13936947c7bSOliver Tappe uint8 c1 14036947c7bSOliver Tappe = (max_c(srcHandle[0], dstHandle[0]) * dstHandle[3] 14173a2ffbaSStephan Aßmus + srcHandle[0] * (255 - dstHandle[3])) / 255; 14236947c7bSOliver Tappe uint8 c2 14336947c7bSOliver Tappe = (max_c(srcHandle[1], dstHandle[1]) * dstHandle[3] 14473a2ffbaSStephan Aßmus + srcHandle[1] * (255 - dstHandle[3])) / 255; 14536947c7bSOliver Tappe uint8 c3 14636947c7bSOliver Tappe = (max_c(srcHandle[2], dstHandle[2]) * dstHandle[3] 14773a2ffbaSStephan Aßmus + srcHandle[2] * (255 - dstHandle[3])) / 255; 14836947c7bSOliver Tappe blend_colors(dstHandle, 14936947c7bSOliver Tappe (srcHandle[3] * alphaOverride) / 255, c1, c2, c3); 15073a2ffbaSStephan Aßmus } 15173a2ffbaSStephan Aßmus srcHandle += 4; 15273a2ffbaSStephan Aßmus dstHandle += 4; 15373a2ffbaSStephan Aßmus } 15473a2ffbaSStephan Aßmus src += bpr; 15573a2ffbaSStephan Aßmus dst += bpr; 15673a2ffbaSStephan Aßmus } 15773a2ffbaSStephan Aßmus break; 15873a2ffbaSStephan Aßmus 15973a2ffbaSStephan Aßmus case MODE_DARKEN: 16073a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 16173a2ffbaSStephan Aßmus uint8* srcHandle = src; 16273a2ffbaSStephan Aßmus uint8* dstHandle = dst; 16373a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 16473a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 16573a2ffbaSStephan Aßmus // compose 16636947c7bSOliver Tappe uint8 c1 16736947c7bSOliver Tappe = (min_c(srcHandle[0], dstHandle[0]) * dstHandle[3] 16873a2ffbaSStephan Aßmus + srcHandle[0] * (255 - dstHandle[3])) / 255; 16936947c7bSOliver Tappe uint8 c2 17036947c7bSOliver Tappe = (min_c(srcHandle[1], dstHandle[1]) * dstHandle[3] 17173a2ffbaSStephan Aßmus + srcHandle[1] * (255 - dstHandle[3])) / 255; 17236947c7bSOliver Tappe uint8 c3 17336947c7bSOliver Tappe = (min_c(srcHandle[2], dstHandle[2]) * dstHandle[3] 17473a2ffbaSStephan Aßmus + srcHandle[2] * (255 - dstHandle[3])) / 255; 17536947c7bSOliver Tappe blend_colors(dstHandle, 17636947c7bSOliver Tappe (srcHandle[3] * alphaOverride) / 255, c1, c2, c3); 17773a2ffbaSStephan Aßmus } 17873a2ffbaSStephan Aßmus srcHandle += 4; 17973a2ffbaSStephan Aßmus dstHandle += 4; 18073a2ffbaSStephan Aßmus } 18173a2ffbaSStephan Aßmus src += bpr; 18273a2ffbaSStephan Aßmus dst += bpr; 18373a2ffbaSStephan Aßmus } 18473a2ffbaSStephan Aßmus break; 18573a2ffbaSStephan Aßmus 18673a2ffbaSStephan Aßmus case MODE_REPLACE_RED: 18773a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 18873a2ffbaSStephan Aßmus uint8* srcHandle = src; 18973a2ffbaSStephan Aßmus uint8* dstHandle = dst; 19073a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 19173a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 19273a2ffbaSStephan Aßmus // compose 19373a2ffbaSStephan Aßmus uint32 alpha = srcHandle[3] * alphaOverride; 19473a2ffbaSStephan Aßmus dstHandle[2] = (srcHandle[2] * alpha 19573a2ffbaSStephan Aßmus + dstHandle[2] * (65025 - alpha)) / 65025; 19673a2ffbaSStephan Aßmus } 19773a2ffbaSStephan Aßmus srcHandle += 4; 19873a2ffbaSStephan Aßmus dstHandle += 4; 19973a2ffbaSStephan Aßmus } 20073a2ffbaSStephan Aßmus src += bpr; 20173a2ffbaSStephan Aßmus dst += bpr; 20273a2ffbaSStephan Aßmus } 20373a2ffbaSStephan Aßmus break; 20473a2ffbaSStephan Aßmus 20573a2ffbaSStephan Aßmus case MODE_REPLACE_GREEN: 20673a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 20773a2ffbaSStephan Aßmus uint8* srcHandle = src; 20873a2ffbaSStephan Aßmus uint8* dstHandle = dst; 20973a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 21073a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 21173a2ffbaSStephan Aßmus // compose 21273a2ffbaSStephan Aßmus uint32 alpha = srcHandle[3] * alphaOverride; 21373a2ffbaSStephan Aßmus dstHandle[1] = (srcHandle[1] * alpha 21473a2ffbaSStephan Aßmus + dstHandle[1] * (65025 - alpha)) / 65025; 21573a2ffbaSStephan Aßmus } 21673a2ffbaSStephan Aßmus srcHandle += 4; 21773a2ffbaSStephan Aßmus dstHandle += 4; 21873a2ffbaSStephan Aßmus } 21973a2ffbaSStephan Aßmus src += bpr; 22073a2ffbaSStephan Aßmus dst += bpr; 22173a2ffbaSStephan Aßmus } 22273a2ffbaSStephan Aßmus break; 22373a2ffbaSStephan Aßmus 22473a2ffbaSStephan Aßmus case MODE_REPLACE_BLUE: 22573a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 22673a2ffbaSStephan Aßmus uint8* srcHandle = src; 22773a2ffbaSStephan Aßmus uint8* dstHandle = dst; 22873a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 22973a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 23073a2ffbaSStephan Aßmus // compose 23173a2ffbaSStephan Aßmus uint32 alpha = srcHandle[3] * alphaOverride; 23273a2ffbaSStephan Aßmus dstHandle[0] = (srcHandle[0] * alpha 23373a2ffbaSStephan Aßmus + dstHandle[0] * (65025 - alpha)) / 65025; 23473a2ffbaSStephan Aßmus } 23573a2ffbaSStephan Aßmus srcHandle += 4; 23673a2ffbaSStephan Aßmus dstHandle += 4; 23773a2ffbaSStephan Aßmus } 23873a2ffbaSStephan Aßmus src += bpr; 23973a2ffbaSStephan Aßmus dst += bpr; 24073a2ffbaSStephan Aßmus } 24173a2ffbaSStephan Aßmus break; 24273a2ffbaSStephan Aßmus 24373a2ffbaSStephan Aßmus case MODE_MULTIPLY_INVERSE_ALPHA: 24473a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 24573a2ffbaSStephan Aßmus uint8* srcHandle = src; 24673a2ffbaSStephan Aßmus uint8* dstHandle = dst; 24773a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 24873a2ffbaSStephan Aßmus // compose 24973a2ffbaSStephan Aßmus uint8 temp = min_c(dstHandle[3], 255 - srcHandle[3]); 25036947c7bSOliver Tappe dstHandle[3] = ( 25136947c7bSOliver Tappe dstHandle[3] * (255 - alphaOverride) 25236947c7bSOliver Tappe + temp * alphaOverride 25336947c7bSOliver Tappe ) / 255; 25473a2ffbaSStephan Aßmus srcHandle += 4; 25573a2ffbaSStephan Aßmus dstHandle += 4; 25673a2ffbaSStephan Aßmus } 25773a2ffbaSStephan Aßmus src += bpr; 25873a2ffbaSStephan Aßmus dst += bpr; 25973a2ffbaSStephan Aßmus } 26073a2ffbaSStephan Aßmus break; 26173a2ffbaSStephan Aßmus 26273a2ffbaSStephan Aßmus case MODE_MULTIPLY_ALPHA: 26373a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 26473a2ffbaSStephan Aßmus uint8* srcHandle = src; 26573a2ffbaSStephan Aßmus uint8* dstHandle = dst; 26673a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 26773a2ffbaSStephan Aßmus // compose 26873a2ffbaSStephan Aßmus uint8 temp = min_c(dstHandle[3], srcHandle[3]); 26936947c7bSOliver Tappe dstHandle[3] = ( 27036947c7bSOliver Tappe dstHandle[3] * (255 - alphaOverride) 27136947c7bSOliver Tappe + temp * alphaOverride 27236947c7bSOliver Tappe ) / 255; 27373a2ffbaSStephan Aßmus srcHandle += 4; 27473a2ffbaSStephan Aßmus dstHandle += 4; 27573a2ffbaSStephan Aßmus } 27673a2ffbaSStephan Aßmus src += bpr; 27773a2ffbaSStephan Aßmus dst += bpr; 27873a2ffbaSStephan Aßmus } 27973a2ffbaSStephan Aßmus break; 28073a2ffbaSStephan Aßmus 28173a2ffbaSStephan Aßmus case MODE_LUMINANCE: 28273a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 28373a2ffbaSStephan Aßmus uint8* srcHandle = src; 28473a2ffbaSStephan Aßmus uint8* dstHandle = dst; 28573a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 28673a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 28773a2ffbaSStephan Aßmus // compose 28873a2ffbaSStephan Aßmus uint8 r = dstHandle[2]; 28973a2ffbaSStephan Aßmus uint8 g = dstHandle[1]; 29073a2ffbaSStephan Aßmus uint8 b = dstHandle[0]; 29173a2ffbaSStephan Aßmus uint8 alpha = dstHandle[3]; 29236947c7bSOliver Tappe replace_luminance(r, g, b, srcHandle[2], srcHandle[1], 29336947c7bSOliver Tappe srcHandle[0]); 29436947c7bSOliver Tappe blend_colors(dstHandle, 29536947c7bSOliver Tappe (srcHandle[3] * alphaOverride) / 255, b, g, r); 29673a2ffbaSStephan Aßmus dstHandle[3] = alpha; 29773a2ffbaSStephan Aßmus } 29873a2ffbaSStephan Aßmus srcHandle += 4; 29973a2ffbaSStephan Aßmus dstHandle += 4; 30073a2ffbaSStephan Aßmus } 30173a2ffbaSStephan Aßmus src += bpr; 30273a2ffbaSStephan Aßmus dst += bpr; 30373a2ffbaSStephan Aßmus } 30473a2ffbaSStephan Aßmus break; 30573a2ffbaSStephan Aßmus 30673a2ffbaSStephan Aßmus case MODE_INVERSE_MULTIPLY: 30773a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 30873a2ffbaSStephan Aßmus uint8* srcHandle = src; 30973a2ffbaSStephan Aßmus uint8* dstHandle = dst; 31073a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 31173a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 31273a2ffbaSStephan Aßmus // compose 31336947c7bSOliver Tappe uint8 c1 = 255 - ( 31436947c7bSOliver Tappe (((255 - srcHandle[0]) * (255 - dstHandle[0])) 31536947c7bSOliver Tappe / 255) * dstHandle[3] 31636947c7bSOliver Tappe + (255 - srcHandle[0]) * (255 - dstHandle[3]) 31736947c7bSOliver Tappe ) / 255; 31836947c7bSOliver Tappe uint8 c2 = 255 - ( 31936947c7bSOliver Tappe (((255 - srcHandle[1]) * (255 - dstHandle[1])) 32036947c7bSOliver Tappe / 255) * dstHandle[3] 32136947c7bSOliver Tappe + (255 - srcHandle[1]) * (255 - dstHandle[3]) 32236947c7bSOliver Tappe ) / 255; 32336947c7bSOliver Tappe uint8 c3 = 255 - ( 32436947c7bSOliver Tappe (((255 - srcHandle[2]) * (255 - dstHandle[2])) 32536947c7bSOliver Tappe / 255) * dstHandle[3] 32636947c7bSOliver Tappe + (255 - srcHandle[2]) * (255 - dstHandle[3]) 32736947c7bSOliver Tappe ) / 255; 32836947c7bSOliver Tappe blend_colors(dstHandle, 32936947c7bSOliver Tappe (srcHandle[3] * alphaOverride) / 255, c1, c2, c3); 33073a2ffbaSStephan Aßmus } 33173a2ffbaSStephan Aßmus srcHandle += 4; 33273a2ffbaSStephan Aßmus dstHandle += 4; 33373a2ffbaSStephan Aßmus } 33473a2ffbaSStephan Aßmus src += bpr; 33573a2ffbaSStephan Aßmus dst += bpr; 33673a2ffbaSStephan Aßmus } 33773a2ffbaSStephan Aßmus break; 33873a2ffbaSStephan Aßmus 33973a2ffbaSStephan Aßmus case MODE_MULTIPLY: 34073a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 34173a2ffbaSStephan Aßmus uint8* srcHandle = src; 34273a2ffbaSStephan Aßmus uint8* dstHandle = dst; 34373a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 34473a2ffbaSStephan Aßmus if (srcHandle[3] > 0) { 34573a2ffbaSStephan Aßmus // compose 34636947c7bSOliver Tappe uint8 c1 = ( 34736947c7bSOliver Tappe ((srcHandle[0] * dstHandle[0]) / 255) 34836947c7bSOliver Tappe * dstHandle[3] 34936947c7bSOliver Tappe + srcHandle[0] * (255 - dstHandle[3]) 35036947c7bSOliver Tappe ) / 255; 35136947c7bSOliver Tappe uint8 c2 = ( 35236947c7bSOliver Tappe ((srcHandle[1] * dstHandle[1]) / 255) 35336947c7bSOliver Tappe * dstHandle[3] 35436947c7bSOliver Tappe + srcHandle[1] * (255 - dstHandle[3]) 35536947c7bSOliver Tappe ) / 255; 35636947c7bSOliver Tappe uint8 c3 = ( 35736947c7bSOliver Tappe ((srcHandle[2] * dstHandle[2]) / 255) 35836947c7bSOliver Tappe * dstHandle[3] 35936947c7bSOliver Tappe + srcHandle[2] * (255 - dstHandle[3]) 36036947c7bSOliver Tappe ) / 255; 36136947c7bSOliver Tappe blend_colors(dstHandle, 36236947c7bSOliver Tappe (srcHandle[3] * alphaOverride) / 255, c1, c2, c3); 36373a2ffbaSStephan Aßmus } 36473a2ffbaSStephan Aßmus srcHandle += 4; 36573a2ffbaSStephan Aßmus dstHandle += 4; 36673a2ffbaSStephan Aßmus } 36773a2ffbaSStephan Aßmus src += bpr; 36873a2ffbaSStephan Aßmus dst += bpr; 36973a2ffbaSStephan Aßmus } 37073a2ffbaSStephan Aßmus break; 37173a2ffbaSStephan Aßmus 37273a2ffbaSStephan Aßmus case MODE_NORMAL: 37373a2ffbaSStephan Aßmus default: 37473a2ffbaSStephan Aßmus if (alphaOverride == 255) { 37573a2ffbaSStephan Aßmus // use an optimized version that composes the bitmaps directly 37673a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 37773a2ffbaSStephan Aßmus uint8* srcHandle = src; 37873a2ffbaSStephan Aßmus uint8* dstHandle = dst; 37973a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 38073a2ffbaSStephan Aßmus blend_colors(dstHandle, srcHandle); 38173a2ffbaSStephan Aßmus srcHandle += 4; 38273a2ffbaSStephan Aßmus dstHandle += 4; 38373a2ffbaSStephan Aßmus } 38473a2ffbaSStephan Aßmus src += bpr; 38573a2ffbaSStephan Aßmus dst += bpr; 38673a2ffbaSStephan Aßmus } 38773a2ffbaSStephan Aßmus } else { 38873a2ffbaSStephan Aßmus for (; top <= bottom; top++) { 38973a2ffbaSStephan Aßmus uint8* srcHandle = src; 39073a2ffbaSStephan Aßmus uint8* dstHandle = dst; 39173a2ffbaSStephan Aßmus for (int32 x = left; x <= right; x++) { 39273a2ffbaSStephan Aßmus blend_colors(dstHandle, srcHandle, alphaOverride); 39373a2ffbaSStephan Aßmus srcHandle += 4; 39473a2ffbaSStephan Aßmus dstHandle += 4; 39573a2ffbaSStephan Aßmus } 39673a2ffbaSStephan Aßmus src += bpr; 39773a2ffbaSStephan Aßmus dst += bpr; 39873a2ffbaSStephan Aßmus } 39973a2ffbaSStephan Aßmus } 40073a2ffbaSStephan Aßmus break; 40173a2ffbaSStephan Aßmus } 40273a2ffbaSStephan Aßmus 40373a2ffbaSStephan Aßmus return status; 40473a2ffbaSStephan Aßmus } 40573a2ffbaSStephan Aßmus 40636947c7bSOliver Tappe 40773a2ffbaSStephan Aßmus // Unarchive 40873a2ffbaSStephan Aßmus status_t 40973a2ffbaSStephan Aßmus Layer::Unarchive(const BMessage* archive) 41073a2ffbaSStephan Aßmus { 41173a2ffbaSStephan Aßmus if (!archive) 41273a2ffbaSStephan Aßmus return B_BAD_VALUE; 41373a2ffbaSStephan Aßmus 41473a2ffbaSStephan Aßmus // restore attributes 41573a2ffbaSStephan Aßmus float alpha; 41673a2ffbaSStephan Aßmus if (archive->FindFloat("alpha", &alpha) == B_OK) { 41773a2ffbaSStephan Aßmus constrain(alpha, 0.0, 1.0); 41873a2ffbaSStephan Aßmus fAlpha = alpha; 41973a2ffbaSStephan Aßmus } else 42073a2ffbaSStephan Aßmus fAlpha = 1.0; 42173a2ffbaSStephan Aßmus if (archive->FindInt32("mode", (int32*)&fMode) < B_OK) 42273a2ffbaSStephan Aßmus fMode = MODE_NORMAL; 42373a2ffbaSStephan Aßmus if (archive->FindInt32("flags", (int32*)&fFlags) < B_OK) 42473a2ffbaSStephan Aßmus fFlags = 0; 42573a2ffbaSStephan Aßmus 42673a2ffbaSStephan Aßmus // delete current contents 42773a2ffbaSStephan Aßmus delete fBitmap; 42873a2ffbaSStephan Aßmus fBitmap = NULL; 42973a2ffbaSStephan Aßmus 43073a2ffbaSStephan Aßmus status_t status = extract_bitmap(&fBitmap, archive, "current bitmap"); 43173a2ffbaSStephan Aßmus if (status < B_OK) 43273a2ffbaSStephan Aßmus return status; 43373a2ffbaSStephan Aßmus 43473a2ffbaSStephan Aßmus // "bounds" is where the layer actually has content 43573a2ffbaSStephan Aßmus BRect bounds; 43673a2ffbaSStephan Aßmus if (archive->FindRect("bounds", &bounds) == B_OK) 43773a2ffbaSStephan Aßmus fBounds = bounds; 43873a2ffbaSStephan Aßmus else 43973a2ffbaSStephan Aßmus fBounds.Set(0.0, 0.0, -1.0, -1.0); 44073a2ffbaSStephan Aßmus 44173a2ffbaSStephan Aßmus // validate status of fBitmap 44273a2ffbaSStephan Aßmus if (!fBitmap) 44373a2ffbaSStephan Aßmus return B_ERROR; 44473a2ffbaSStephan Aßmus 44573a2ffbaSStephan Aßmus status = fBitmap->InitCheck(); 44673a2ffbaSStephan Aßmus if (status < B_OK) { 44773a2ffbaSStephan Aßmus delete fBitmap; 44873a2ffbaSStephan Aßmus fBitmap = NULL; 44973a2ffbaSStephan Aßmus } 45073a2ffbaSStephan Aßmus 45173a2ffbaSStephan Aßmus return status; 45273a2ffbaSStephan Aßmus } 453