add BitmapDrawable::tilemode

This commit is contained in:
侯歌 2021-12-03 17:24:23 +08:00
parent e54f8955af
commit dd4fae01a3
3 changed files with 73 additions and 19 deletions

View File

@ -13,6 +13,7 @@ BitmapDrawable::BitmapState::BitmapState(){
mTint = nullptr;
mTransparency= -1;
mTintMode = DEFAULT_TINT_MODE;
mTileModeX =mTileModeY=-1;
mAutoMirrored= false;
mSrcDensityOverride=0;
mTargetDensity=160;
@ -33,8 +34,8 @@ BitmapDrawable::BitmapState::BitmapState(const BitmapState&bitmapState){
mChangingConfigurations = bitmapState.mChangingConfigurations;
mGravity = bitmapState.mGravity;
mTransparency= bitmapState.mTransparency;
//mTileModeX = bitmapState.mTileModeX;
//mTileModeY = bitmapState.mTileModeY;
mTileModeX = bitmapState.mTileModeX;
mTileModeY = bitmapState.mTileModeY;
mSrcDensityOverride = bitmapState.mSrcDensityOverride;
mTargetDensity = bitmapState.mTargetDensity;
mBaseAlpha = bitmapState.mBaseAlpha;
@ -123,6 +124,31 @@ int BitmapDrawable::getIntrinsicHeight()const{
return mBitmapHeight;
}
int BitmapDrawable::getTileModeX()const{
return mBitmapState->mTileModeX;
}
int BitmapDrawable::getTileModeY()const{
return mBitmapState->mTileModeY;
}
void BitmapDrawable::setTileModeX(int mode){
setTileModeXY(mode,mBitmapState->mTileModeY);
}
void BitmapDrawable::setTileModeY(int mode){
setTileModeXY(mBitmapState->mTileModeX,mode);
}
void BitmapDrawable::setTileModeXY(int xmode,int ymode){
if(mBitmapState->mTileModeX!=xmode||mBitmapState->mTileModeY!=ymode){
mBitmapState->mTileModeX=xmode;
mBitmapState->mTileModeY=ymode;
mDstRectAndInsetsDirty =true;
invalidateSelf();
}
}
void BitmapDrawable::setAutoMirrored(bool mirrored){
if(mBitmapState->mAutoMirrored!=mirrored){
mBitmapState->mAutoMirrored=mirrored;
@ -278,9 +304,19 @@ void BitmapDrawable::draw(Canvas&canvas){
LOGD_IF(mBounds.empty(),"%p's bounds is empty,skip drawing,otherwise will caused crash",this);
canvas.save();
canvas.rectangle(mBounds.left,mBounds.top,mBounds.width,mBounds.height);
if(mBitmapState->mTileModeX>=0||mBitmapState->mTileModeY>=0){
RefPtr<SurfacePattern> pat=SurfacePattern::create(mBitmapState->mBitmap);
switch(mBitmapState->mTileModeX){
case TileMode::CLAMP : pat->set_extend(Pattern::Extend::PAD) ; break;
case TileMode::REPEAT: pat->set_extend(Pattern::Extend::REPEAT); break;
case TileMode::MIRROR: pat->set_extend(Pattern::Extend::REFLECT);break;
}
canvas.set_source(pat);
canvas.fill();
}else{
canvas.clip();
const bool scaled=(mBounds.width !=mBitmapWidth) || (mBounds.height != mBitmapHeight);
if (scaled) {
if ( (mBounds.width !=mBitmapWidth) || (mBounds.height != mBitmapHeight) ) {
canvas.scale(dw/sw,dh/sh);
dx /= fx; dy /= fy;
dw /= fx; dh /= fy;
@ -288,13 +324,12 @@ void BitmapDrawable::draw(Canvas&canvas){
if(needMirroring()){
canvas.translate(mDstRect.width,0);
canvas.scale(-1.f,1.f);LOGD("mirrored....");
canvas.scale(-1.f,1.f);
}
canvas.set_source(mBitmapState->mBitmap, dx, dy );
canvas.get_source_for_surface()->set_filter(SurfacePattern::Filter::BEST);
canvas.paint_with_alpha(alpha);
if(scaled)canvas.scale(sw/dw,sh/dh);
}
canvas.restore();
if(mTintFilter)mTintFilter->apply(canvas,mBounds);
}
@ -311,7 +346,12 @@ Drawable*BitmapDrawable::inflate(Context*ctx,const AttributeSet&atts){
bool filter=atts.getBoolean("filter",true);
bool mipMap=atts.getBoolean("mipMap",true);
int gravity=atts.getGravity("gravity",Gravity::CENTER);
int tileMode=0;//"disabled" | "clamp" | "repeat" | "mirror";
static std::map<const std::string,int>kvs={
{"disabled",TileMode::DISABLED}, {"clamp",TileMode::CLAMP},
{"repeat",TileMode::REPEAT}, {"mirror",TileMode::MIRROR}};
const int tileMode = atts.getInt("tileMode",kvs,-1);
int tileModeX= atts.getInt("tileModeX",kvs,tileMode);
int tileModeY= atts.getInt("tileModeY",kvs,tileMode);
std::string path=src;
if(ctx==nullptr)path=atts.getAbsolutePath(src);
@ -320,6 +360,7 @@ Drawable*BitmapDrawable::inflate(Context*ctx,const AttributeSet&atts){
BitmapDrawable*d=new BitmapDrawable(path);
LOGD("bitmap=%p",d);
d->setGravity(gravity);
d->setTileModeXY(tileModeX,tileModeY);
return d;
}

View File

@ -6,6 +6,12 @@
using namespace Cairo;
namespace cdroid{
enum TileMode{
DISABLED=-1,
CLAMP =0,
REPEAT=1,
MIRROR=2
};
class BitmapDrawable:public Drawable{
private:
class BitmapState:public std::enable_shared_from_this<BitmapState>,public ConstantState{
@ -19,6 +25,8 @@ private:
std::vector<int>mThemeAttrs;
ColorStateList* mTint;
int mTintMode;
int mTileModeX;
int mTileModeY;
int mSrcDensityOverride;
int mTargetDensity;
RefPtr<ImageSurface>mBitmap;
@ -57,6 +65,11 @@ public:
int getIntrinsicWidth()const override;
int getIntrinsicHeight()const override;
int getOpacity()override;
int getTileModeX()const;
int getTileModeY()const;
void setTileModeX(int);
void setTileModeY(int);
void setTileModeXY(int,int);
void setAutoMirrored(bool mirrored)override;
bool isAutoMirrored()override;
void setTintList(ColorStateList*lst)override;

View File

@ -154,7 +154,7 @@ Drawable* ProgressBar::tileify(Drawable* drawable, bool clip){
if (dynamic_cast<BitmapDrawable*>(drawable)) {
std::shared_ptr<Drawable::ConstantState> cs = drawable->getConstantState();
BitmapDrawable* clone = (BitmapDrawable*) cs->newDrawable();
//clone->setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
clone->setTileModeXY(TileMode::REPEAT, TileMode::CLAMP);
if (mSampleWidth <= 0) {
mSampleWidth = clone->getIntrinsicWidth();