From dd4fae01a36f0ba03861198bacd500f4623b62f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=AF=E6=AD=8C?= Date: Fri, 3 Dec 2021 17:24:23 +0800 Subject: [PATCH] add BitmapDrawable::tilemode --- src/gui/drawables/bitmapdrawable.cc | 77 ++++++++++++++++++++++------- src/gui/drawables/bitmapdrawable.h | 13 +++++ src/gui/widget/progressbar.cc | 2 +- 3 files changed, 73 insertions(+), 19 deletions(-) diff --git a/src/gui/drawables/bitmapdrawable.cc b/src/gui/drawables/bitmapdrawable.cc index 57012619..004f82b2 100755 --- a/src/gui/drawables/bitmapdrawable.cc +++ b/src/gui/drawables/bitmapdrawable.cc @@ -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,23 +304,32 @@ 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); - canvas.clip(); - const bool scaled=(mBounds.width !=mBitmapWidth) || (mBounds.height != mBitmapHeight); - if (scaled) { - canvas.scale(dw/sw,dh/sh); - dx /= fx; dy /= fy; - dw /= fx; dh /= fy; - } - if(needMirroring()){ - canvas.translate(mDstRect.width,0); - canvas.scale(-1.f,1.f);LOGD("mirrored...."); + if(mBitmapState->mTileModeX>=0||mBitmapState->mTileModeY>=0){ + RefPtr 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(); + if ( (mBounds.width !=mBitmapWidth) || (mBounds.height != mBitmapHeight) ) { + canvas.scale(dw/sw,dh/sh); + dx /= fx; dy /= fy; + dw /= fx; dh /= fy; + } + + if(needMirroring()){ + canvas.translate(mDstRect.width,0); + 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); } - 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::mapkvs={ + {"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; } diff --git a/src/gui/drawables/bitmapdrawable.h b/src/gui/drawables/bitmapdrawable.h index b3d21d24..725c838b 100755 --- a/src/gui/drawables/bitmapdrawable.h +++ b/src/gui/drawables/bitmapdrawable.h @@ -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,public ConstantState{ @@ -19,6 +25,8 @@ private: std::vectormThemeAttrs; ColorStateList* mTint; int mTintMode; + int mTileModeX; + int mTileModeY; int mSrcDensityOverride; int mTargetDensity; RefPtrmBitmap; @@ -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; diff --git a/src/gui/widget/progressbar.cc b/src/gui/widget/progressbar.cc index 8b18082c..a0b8e9e6 100755 --- a/src/gui/widget/progressbar.cc +++ b/src/gui/widget/progressbar.cc @@ -154,7 +154,7 @@ Drawable* ProgressBar::tileify(Drawable* drawable, bool clip){ if (dynamic_cast(drawable)) { std::shared_ptr 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();