B4A Library ABExtDrawing 1.0

Discussion in 'Additional libraries, classes and official updates' started by alwaysbusy, Feb 3, 2012.

  1. alwaysbusy

    alwaysbusy Expert Licensed User

    ABExtDrawing 1.7

    ABExtDrawing is a wrapper around the Android Drawing classes.

    14/08/2012: Updated to version 1.7

    Bugfixes and additional functions for blurring and masks.

    16/02/2012: Updated to version 1.1

    It makes it possible to access all the drawing functions of the Canvas. It is like the B4A canvas, but you can also use all Paints.

    Several sub objects are also included:
    ABPaint: a wrapper for thePaint class
    ABMatrix: a wrapper for the Matrix class
    ABRegion: a wrapper for the Region class
    ABColorMatrix: a wrapper for the ColorMatrix class
    ABCamera: a wrapper for the Camera class [NEW version 1.1]
    ABRgbFunctions: several functions to manipulate RGB values

    Also two extended classes
    ABRectF: a wrapper around the RectF class. B4A contains the Rect class, but to use some of the functions of this library I needed the float version of Rect.
    ABPath: a full wrapper for the Path class. B4A contains the Path class but only exposes LineTo. ABPath exposes all functions (like addArc, addOval, etc...)

    This lib is to big to list all functions, but a lot of them are used in the attached demo. It is a B4A translation of the Thermometer project on Mind The Robot

    [​IMG]

    How to use this library:

    The main object is ABExtDrawing. You pass the B4A canvas to each function:
    Code:
    Sub Globals
            
    Dim ExDraw As ABExtDrawing
            
    Dim MyCanvas As Canvas
            
    Dim Panel1 as Panel
    end Sub

    Sub Activity_Create(FirstTime As Boolean)
            
    If FirstTime Then
          
    Activity.LoadLayout("2")
          MyCanvas.Initialize(Panel1)   
       
    End If
            drawRim(MyCanvas)
    End Sub

    Sub drawRim(Canv As Canvas)
       
    ' first, draw the metallic body
       ExDraw.drawOval(Canv, rimRect, rimPaint)
       
    ' now the outer rim circle
       ExDraw.drawOval(Canv, rimRect, rimCirclePaint)
    End Sub
    The fun part is you can create all kind of Paints:
    Code:
    ' the linear gradient Is a Bit skewed For realism
       rimPaint.Initialize
       rimPaint.SetFlags(rimPaint.flag_ANTI_ALIAS_FLAG)
       rimPaint.SetLinearGradient2(
    1,0.400.00.601.0Colors.RGB(0xf00xf50xf0),Colors.RGB(0x300x310x30),rimPaint.ShaderTileMode_CLAMP)   
       rimPaint.DoShaderSingle(
    1)

       rimCirclePaint.Initialize
       rimCirclePaint.SetAntiAlias(
    True)
       rimCirclePaint.SetStyle(rimCirclePaint.Style_STROKE)
       rimCirclePaint.SetColor(
    Colors.ARGB(0x4f0x330x360x33))
       rimCirclePaint.SetStrokeWidth(
    0.005)
    or make extended Paths:
    Code:
    handPath.Initialize
       handPath.moveTo(
    0.50.5 + 0.2)
       handPath.lineTo(
    0.5 - 0.0100.5 + 0.2 - 0.007)
       handPath.lineTo(
    0.5 - 0.0020.5 - 0.32)
       handPath.lineTo(
    0.5 + 0.0020.5 - 0.32)
       handPath.lineTo(
    0.5 + 0.0100.5 + 0.2 - 0.007)
       handPath.lineTo(
    0.50.5 + 0.2)
       handPath.addCircle(
    0.50.50.025, handPath.Direction_CW)
    You can also use the Save and Restore functions of the canvas:
    Code:
    Sub drawScale(Canv As Canvas)
       ExDraw.drawOval(Canv, scaleRect, ScalePaint)

       ExDraw.save2(Canv, ExDraw.MATRIX_SAVE_FLAG)
       
    Dim i As Int
       
    Dim y1 As Float
       
    Dim y2 As Float
       
    Dim value As Int
       
    Dim valueString As String
       
    For i = 0 To totalNicks
          y1 = scaleRect.top
          y2 = y1 - 
    0.020
             
          ExDraw.drawLine(Canv, 
    0.5, y1, 0.5, y2, ScalePaint)
             
          
    If (i Mod 5 = 0Then
             value = nickToDegree(i)
             
    If (value >= minDegrees AND value <= maxDegrees) Then
                valueString = value
                ExDraw.drawText(Canv, valueString, 
    0.5, y2 - 0.015, ScalePaint)
             
    End If
          
    End If
             
          ExDraw.rotate2(Canv, degreesPerNick, 
    0.50.5)
       
    Next
       ExDraw.restore(Canv)
    End Sub
    For more information on what is possible, look into the Android documentation

    There is a new article on the Camera class (see the AB3DCamera project) that shows you how to make a 3D list with ABExtDrawing 1.1. The article can be found at Alwaysbusy's Corner. The project is also attached to this post.

    [​IMG]
     

    Attached Files:

    Last edited: Aug 14, 2012
  2. joseluis

    joseluis Active Member Licensed User

    Thank you for sharing! This library has so many possibilities, and the example is very useful. :icon_clap:.
     
  3. peacemaker

    peacemaker Well-Known Member Licensed User

    Interesting. Is it possible to get normally sized grayscaled bitmap from a source one ?
     
  4. alwaysbusy

    alwaysbusy Expert Licensed User

    GreyScale example

    @peacemaker: I've updated the library so that you also can use the class ABColorMatrix. Now you can write a GreyScale function like this:

    Code:
    Sub GrayScale(bmp As BitmapAs Bitmap
        
    Dim bmpGrayscale As Bitmap
        bmpGrayscale.InitializeMutable(bmp.Width, bmp.height)
        
    Dim c As Canvas
        c.Initialize2(bmpGrayscale)

        
    Dim paint As ABPaint
        
    paint.Initialize
       
        
    Dim mat As ABColorMatrix
        mat.Initialize
        mat.SetSaturation(
    0)

        
    paint.SetColorMatrixColorFilter2(mat)

        ExDraw.drawBitmap2(c, bmp, 
    00paint)

        
    Return bmpGrayscale
    End Sub
     
  5. peacemaker

    peacemaker Well-Known Member Licensed User

    Wow ! Thank you very much !
     
  6. bluejay

    bluejay Active Member Licensed User

    This is a great library addition - thanks for sharing this :sign0142:

    Also a very nice example.

    Some comments regarding the example:
    Activity objects need to initialized 'everytime' the activity is created so

    Activity.LoadLayout("2")
    MyCanvas.Initialize(Panel1)

    should not be inside an 'If Firstime then'

    Similarly the PhoneSensors objects should be Dim'd in Process Globals.

    The B4A version is much easier to read than the Java version - great work on the B4A conversion.:icon_clap:

    thanks

    bluejay
     
  7. bparent

    bparent Member Licensed User

     
  8. hdtvirl

    hdtvirl Active Member Licensed User

    Thanks for the Library

    Always Busy, If I was in Belgium I would buy you an Orval Beer or what ever else you wanted to drink, This work is outstanding.

    I have signed up for your news letter also.

    Regards


    hdtvirl
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    Thank you for sharing this great library!
     
  10. alwaysbusy

    alwaysbusy Expert Licensed User

    Glad I could help :)

    @bparent: a wrapper is actually very easy to write. It is just a lot of typing work. eg for the Path wrapper:

    What I did was include the real Java object as a protected property:
    Code:
    protected Path mPath;
    Replace all the constructors of Path by Initialize functions. Make sure all parameters you set in the functions are known b4a objects!
    Code:
    public void Initialize() {
          mPath==new 
    Path();
    }
          
    public void Initialize2(ABPath path) {
          mPath = path.mPath;
    }
    I added some of the enums this class needed as finals. You could make subclasses to do this but this is to avoid to many unneeded objects are visible in b4a. There may be a better way to expose Enums in b4a, but I don't know how.
    Code:
    public static final int Direction_CCW=0;
    public static final int Direction_CW=1;
          
    public static final int FillType_EVEN_ODD=0;
    public static final int FillType_INVERSE_EVEN_ODD=1;
    public static final int FillType_INVERSE_WINDING=2;
    public static final int FillType_WINDING=3;
    And then it is just a matter of taking the android documentation next to you and start copying all the functions and making the needed changes.

    Very important: make sure all function names are unique!
    If for example in the documentation there are two addPath functions, you have to give them different names in the wrapper (addPath and addPath2).

    Code:
    public void addPath(ABPath src) {
       mPath.addPath(src.mPath);
    }
                
    public void addPath2(ABPath src, ABMatrix matrix) {
       mPath.addPath(src.mPath, matrix.mMatrix);
    }
    Here is for example part of the ABPath wrapper:

    Code:
    @ShortName("ABPath")
    public static class ABPath {
          protected 
    Path mPath;
          protected Direction direction=
    Path.Direction.CW;
          
    private int mDirection=1;
          
          
    public static final int Direction_CCW=0;
          
    public static final int Direction_CW=1;
          
          
    public static final int FillType_EVEN_ODD=0;
          
    public static final int FillType_INVERSE_EVEN_ODD=1;
          
    public static final int FillType_INVERSE_WINDING=2;
          
    public static final int FillType_WINDING=3;
          
          
    public void Initialize() {
             mPath=new 
    Path();
          
    }
          
          public void Initialize2(ABPath path) {
             mPath = path.mPath;
          }
          
          public void SetDirection(int value) {
             mDirection = value;
             if (value==Direction_CCW) {
                direction = Path.Direction.CCW;            
             } else {
                direction = Path.Direction.CW;
             }
          }
          
          protected void Set(Path path) {
             mPath = path;
          }
          
          public int GetDirection() {
             return mDirection;         
          }
                
          public void addArc(ABRectF oval, float startAngle, float sweepAngle) {
             mPath.addArc(oval.mRectF, startAngle, sweepAngle);
          }
          
          public void addCircle(float x, float y, float radius, int dir) {
             if (dir==Direction_CCW) {
                mPath.addCircle(x, y, radius, Path.Direction.CCW);
             } else {
                mPath.addCircle(x, y, radius, Path.Direction.CW);
             }
          }
          
          public void addOval(ABRectF oval, int dir) {
             if (dir==Direction_CCW) {
                mPath.addOval(oval.mRectF, Path.Direction.CCW);
             } else {
                mPath.addOval(oval.mRectF, Path.Direction.CW);
             }
          }
          
          public void addPath(ABPath src) {
             mPath.addPath(src.mPath);
          }
                
          public void addPath2(ABPath src, ABMatrix matrix) {
             mPath.addPath(src.mPath, matrix.mMatrix);
          }
          
          ...
    }
    Cheers,

    Alwaysbusy
     
  11. alwaysbusy

    alwaysbusy Expert Licensed User

    Version 1.1

    Update version 1.1.

    Added:
    ABCamera: a wrapper for the Camera class

    See the first post for more.
     
  12. thedesolatesoul

    thedesolatesoul Expert Licensed User

    :sign0188:
    This is simply amazing!!!
    I really dont understand most of it to be honest and I thought it was not possible without opengl. Awesome work!!! I just wish I could get my head around it.
     
  13. JogiDroid

    JogiDroid Member Licensed User

  14. alwaysbusy

    alwaysbusy Expert Licensed User

    Yes, all the paint filter effects are included. Some are used in the attached demos.

    Look them up under the Set... functions like:

    paint.SetColorMatrixColorFilter2(mat)
     
  15. lachbus

    lachbus New Member Licensed User

    Thanks man this is great stuff!
    I went into your blog and got stuck for a good hour! You do some seriously fun and great looking things.

    Greetings from Chicago, Stephan
     
  16. alwaysbusy

    alwaysbusy Expert Licensed User

    Thanks Stephan! I've always enjoyed the visual part in programming but there is not a lot to find about this topic on the net. That's why I started the blog. Glad you enjoyed it. :)

    Alwaysbusy
     
  17. bluedude

    bluedude Well-Known Member Licensed User

    Pretty cool but sample project contains not enough comments

    Hi,

    I want to adapt the gauge sample but have no clue what to change. Would be nice to include comments for:

    - how to change the size of the gauge;
    - how to change the values on the scale;
    - how to change the needle.

    Cheers and thanks in advance.
     
  18. NeoTechni

    NeoTechni Well-Known Member Licensed User

    I'm trying to use this but the documentation is nigh nonexistent

    I've taken
    Code:
    Sub DrawScreen
       ExDraw.save2(BG, ExDraw.MATRIX_SAVE_FLAG)
       
       
    Dim dest As Rect 
       dest.Initialize(
    0,0,200,200)
       BG.DrawBitmap(tempbmp, 
    Null, dest)
       drawFace(BG,tempbmp,  
    Activity.Width/2Activity.Height/2,100,100,  1,90)

       ExDraw.restore(BG)
       
    Activity.Invalidate 
    End Sub


    Sub drawFace(myBG As Canvas, BMP As Bitmap, Left As Int, Top As Int, CenterX As Float, CenterY As Float, scale As Float, RotationX As Float) 
       
    ' save the camera state
        mCamera.save

        
    ' translate AND Then rotate the camera
        mCamera.translate(00, CenterY)
        mCamera.rotateX(RotationX)
       mCamera.translate(
    00, -CenterY)

        
        
    ' get the matrix from the camera AND Then restore the camera
        mCamera.getMatrix(mMatrix)
        mCamera.restore()

        
    ' translate AND scale the matrix
        mMatrix.preTranslate(-CenterX, -CenterY)
        mMatrix.postScale(scale, scale)
        mMatrix.postTranslate(Left + CenterX, Top + CenterY)

        
    ' set the light
       Dim cosRotation As Double
       cosRotation = 
    Cos(PI * RotationX / 180)
        
    Dim intensity As Int
       intensity = AMBIENT_LIGHT + (DIFFUSE_LIGHT * cosRotation)
        
    Dim highlightIntensity As Int
       highlightIntensity = (SPECULAR_LIGHT * 
    Power(cosRotation,SHININESS))   
        
    If (intensity > MAX_INTENSITY) Then
            intensity = MAX_INTENSITY
        
    End If
        
    If (highlightIntensity > MAX_INTENSITY) Then
            highlightIntensity = MAX_INTENSITY
        
    End If
        
    Dim light As Int
       light = 
    Colors.rgb(intensity, intensity, intensity)
        
    Dim highlight As Int
       highlight = 
    Colors.rgb(highlightIntensity, highlightIntensity, highlightIntensity)
        mPaint.SetLightingColorFilter(light, highlight)   
        
        
    ' draw the Bitmap
        ExDraw.drawBitmap4(myBG, BMP,  mMatrix, mPaint)
    End Sub
    How do I use it to draw a trapezoid?
    When I try, only the test square draws

    Is there a different way where I can just feed in 4 X/Y coordinates?
    That way I can keep one size a constant length of my choosing?
     
  19. scrat

    scrat Active Member Licensed User

    Thank you for this very useful lib !

    I have a small problem with ABPaint initialize3 function. (null pointer)

    Code:
    'Activity module
    Sub Process_Globals
       
    'These global variables will be declared once when the application starts.
       'These variables can be accessed from all modules.
    Dim ExDraw As ABExtDrawing
    Dim OriPaint As ABPaint
    Dim CopyPaint As ABPaint
    End Sub

    Sub Globals
       
    'These global variables will be redeclared each time the activity is created.
       'These variables can only be accessed from this module.

    End Sub

    Sub Activity_Create(FirstTime As Boolean)

    If FirstTime=True Then
    'contexte original
    OriPaint.Initialize
    OriPaint.SetFlags(OriPaint.flag_ANTI_ALIAS_FLAG)
    OriPaint.SetStyle(OriPaint.Style_STROKE)
    OriPaint.SetStrokeWidth(
    2.5)

    'copy du contexte
    CopyPaint.Initialize3(OriPaint)'null pointer

    End If



    End Sub

    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)

    End Sub

    and a request :
    is it possible to have a property "isinitialized" for ABpath, ABpaint, ABregion, etc ?

    Another request ::sign0013:
    It's possible to add quickReject(Region rgn)
    Very usefull to test with non-rectanglar region

    Thanks again
     
    Last edited: Jun 16, 2012
  20. alwaysbusy

    alwaysbusy Expert Licensed User

    salim safran likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice