├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── scopes │ └── scope_settings.xml └── vcs.xml ├── PaintBrush.iml ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── it │ │ └── moondroid │ │ └── paintbrush │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── it │ │ └── moondroid │ │ └── paintbrush │ │ ├── BrushSelectActivity.java │ │ ├── MainActivity.java │ │ ├── PaintBrushApp.java │ │ ├── dialogs │ │ └── HSVColorPickerDialog.java │ │ ├── drawing │ │ ├── Brush.java │ │ ├── Brushes.java │ │ ├── DrawingView.java │ │ ├── PaintView.java │ │ ├── TouchDistanceResampler.java │ │ └── TouchResampler.java │ │ ├── fragments │ │ └── BrushSelectFragment.java │ │ ├── util │ │ └── ImageUtils.java │ │ └── widget │ │ ├── OpacityPopupWindow.java │ │ ├── PopupSeekBar.java │ │ ├── SizePopupWindow.java │ │ └── ValuePopupWindow.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-nodpi │ ├── brush_01.png │ ├── brush_01_gb45.png │ ├── brush_03.png │ ├── brush_03_gb15.png │ ├── brush_04.png │ ├── brush_05.png │ ├── brush_07.png │ ├── brush_10.png │ ├── brush_10_gb11.png │ ├── brush_10_gb15.png │ ├── brush_12.png │ ├── brush_12_gb15.png │ ├── brush_14.png │ ├── brush_14_gb50.png │ ├── brush_18.png │ ├── brush_18_gb15.png │ ├── brush_19.png │ ├── brush_19_gb15.png │ ├── brush_22.png │ ├── brush_22_gb15.png │ ├── brush_28.png │ ├── brush_32.png │ ├── brush_32_gb12.png │ ├── brush_33.png │ ├── brush_41.png │ ├── brush_41_gb15.png │ ├── brush_42.png │ ├── brush_42_gb15.png │ ├── brush_43.png │ ├── brush_43_gb15.png │ ├── brush_44.png │ ├── brush_44_gb15.png │ ├── brush_45.png │ ├── brush_45_gb15.png │ ├── brush_46.png │ ├── brush_46_gb15.png │ ├── brush_47.png │ ├── brush_47_gb15.png │ ├── brush_48.png │ ├── brush_48_gb15.png │ ├── brush_49.png │ ├── brush_49_gb12.png │ ├── brush_53.png │ ├── brush_54.png │ ├── brush_55.png │ ├── brush_56.png │ ├── brush_60.png │ ├── brush_60_gb50.png │ ├── main_brush_icon_01.png │ ├── main_brush_icon_02.png │ ├── main_brush_icon_03.png │ ├── main_brush_icon_04.png │ ├── main_brush_icon_05.png │ ├── main_brush_icon_06.png │ ├── main_brush_icon_07.png │ ├── main_brush_icon_08.png │ ├── main_brush_icon_09.png │ ├── main_brush_icon_10.png │ ├── main_brush_icon_11.png │ ├── main_brush_icon_12.png │ ├── main_brush_icon_13.png │ ├── main_brush_icon_14.png │ ├── main_brush_icon_15.png │ ├── main_brush_icon_16.png │ ├── main_brush_icon_17.png │ ├── main_brush_icon_18.png │ ├── main_brush_icon_19.png │ ├── main_brush_icon_20.png │ ├── main_brush_icon_21.png │ ├── main_brush_icon_22.png │ ├── main_brush_icon_23.png │ ├── main_brush_icon_24.png │ ├── main_brush_icon_25.png │ ├── main_brush_icon_26.png │ ├── main_brush_icon_27.png │ ├── main_brush_icon_28.png │ ├── main_brush_icon_29.png │ ├── main_brush_icon_30.png │ ├── main_brush_icon_31.png │ ├── main_brush_icon_32.png │ ├── main_brush_icon_33.png │ ├── main_brush_icon_34.png │ ├── main_brush_icon_35.png │ ├── main_brush_icon_36.png │ ├── main_brush_icon_37.png │ ├── main_brush_icon_38.png │ ├── main_brush_icon_39.png │ ├── main_brush_icon_40.png │ ├── main_brush_icon_41.png │ ├── main_brush_icon_42.png │ ├── photobrush_acrylic.png │ ├── photobrush_air_brush.png │ ├── photobrush_fish.png │ ├── photobrush_flowers.png │ ├── photobrush_hard_pastel.png │ ├── photobrush_impress.png │ ├── photobrush_oil.png │ ├── photobrush_oil_pastel.png │ ├── photobrush_pen.png │ ├── photobrush_renoir.png │ ├── photobrush_seurat.png │ ├── photobrush_van_gogh.png │ ├── photobrush_water_color.png │ ├── photobrush_wet_canvas.png │ ├── photobrush_wet_sponge.png │ ├── stylishbrush_air_brush.png │ ├── stylishbrush_ballpoint_pen.png │ ├── stylishbrush_bamboo1.png │ ├── stylishbrush_bamboo2.png │ ├── stylishbrush_calligraphy.png │ ├── stylishbrush_colorless_oil.png │ ├── stylishbrush_coub_knife.png │ ├── stylishbrush_creyon.png │ ├── stylishbrush_felt_pen.png │ ├── stylishbrush_finger.png │ ├── stylishbrush_fish.png │ ├── stylishbrush_flowers.png │ ├── stylishbrush_hard_pastel.png │ ├── stylishbrush_hard_pencil.png │ ├── stylishbrush_head_eraser.png │ ├── stylishbrush_ink_pen.png │ ├── stylishbrush_ink_spot.png │ ├── stylishbrush_knife1.png │ ├── stylishbrush_knife2.png │ ├── stylishbrush_oil.png │ ├── stylishbrush_oil_pastel.png │ ├── stylishbrush_pastel.png │ ├── stylishbrush_pen.png │ ├── stylishbrush_soft_eraser.png │ ├── stylishbrush_soft_pencil.png │ ├── stylishbrush_sponge.png │ ├── stylishbrush_water_color.png │ └── texture01.png │ ├── drawable-xhdpi │ ├── brush_opacity_top_line.png │ ├── brush_scroll.png │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable │ ├── bg_visibility_toggle_selector.xml │ ├── brush_opacity_bottom_bg.png │ ├── brush_opacity_center_mask.png │ ├── brush_opacity_size_bg.9.png │ ├── brush_select.9.png │ ├── brush_selector_background.xml │ ├── brush_size.png │ ├── color_palette_bottom_bg.png │ ├── color_palette_center_mask.png │ ├── color_palette_top_btn.png │ ├── opacity_layer.xml │ ├── palette_brightness.9.png │ ├── palette_pattern.png │ ├── palette_pattern_tile.xml │ ├── palette_shadow.9.png │ ├── photo_view_off.png │ ├── photo_view_on.png │ └── size_layer.xml │ ├── layout │ ├── activity_brush_select.xml │ ├── activity_main.xml │ ├── brush_gridview_item.xml │ ├── fragment_brush_select.xml │ ├── opacity_popup.xml │ └── size_popup.xml │ ├── menu │ └── main.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── brush_attrs.xml │ ├── brush_strings.xml │ ├── brush_styles.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | PaintBrush -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Android API 19 Platform 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PaintBrush.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 19 5 | buildToolsVersion "20.0.0" 6 | 7 | defaultConfig { 8 | applicationId "it.moondroid.paintbrush" 9 | minSdkVersion 14 10 | targetSdkVersion 19 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:support-v4:19.0.0' 25 | compile 'com.joanzapata.android:android-iconify:1.0.6' 26 | } 27 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\marco.granatiero\AppData\Local\Android\android-studio\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/it/moondroid/paintbrush/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/BrushSelectActivity.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.FragmentActivity; 5 | import android.support.v4.app.FragmentTransaction; 6 | 7 | import it.moondroid.paintbrush.fragments.BrushSelectFragment; 8 | 9 | /** 10 | * Created by marco.granatiero on 19/08/2014. 11 | */ 12 | public class BrushSelectActivity extends FragmentActivity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | 18 | setContentView(R.layout.activity_brush_select); 19 | 20 | int brushId = getIntent().getIntExtra(PaintBrushApp.EXTRA_BRUSH_ID, 0); 21 | int brushType = getIntent().getIntExtra(PaintBrushApp.EXTRA_BRUSH_TYPE, 0); 22 | BrushSelectFragment fragment = BrushSelectFragment.newInstance(brushId, brushType); 23 | 24 | FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 25 | ft.replace(R.id.container, fragment); 26 | ft.commit(); 27 | 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/MainActivity.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.Context; 6 | import android.content.DialogInterface; 7 | import android.content.Intent; 8 | import android.graphics.Color; 9 | import android.net.Uri; 10 | import android.os.Bundle; 11 | import android.view.Menu; 12 | import android.view.MenuItem; 13 | import android.view.View; 14 | import android.widget.ImageView; 15 | import android.widget.SeekBar; 16 | import android.widget.Toast; 17 | 18 | import com.joanzapata.android.iconify.IconDrawable; 19 | import com.joanzapata.android.iconify.Iconify; 20 | 21 | import it.moondroid.paintbrush.dialogs.HSVColorPickerDialog; 22 | import it.moondroid.paintbrush.drawing.Brush; 23 | import it.moondroid.paintbrush.drawing.Brushes; 24 | import it.moondroid.paintbrush.drawing.PaintView; 25 | import it.moondroid.paintbrush.util.ImageUtils; 26 | import it.moondroid.paintbrush.widget.OpacityPopupWindow; 27 | import it.moondroid.paintbrush.widget.PopupSeekBar; 28 | import it.moondroid.paintbrush.widget.SizePopupWindow; 29 | 30 | 31 | public class MainActivity extends Activity { 32 | 33 | private PaintView mPaintView; 34 | private PopupSeekBar mSizeSeekBar; 35 | private PopupSeekBar mOpacitySeekBar; 36 | 37 | private ImageView mFirstBrushButton; 38 | 39 | private int mDrawingColor = 0xFF4488CC; //default color 40 | private int mCurrentBrushId = 0; //default brush 41 | 42 | private static final int REQUEST_BRUSH_SELECT = 3; 43 | 44 | @Override 45 | protected void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setContentView(R.layout.activity_main); 48 | 49 | mPaintView = (PaintView) findViewById(R.id.paint_view); 50 | mFirstBrushButton = (ImageView)findViewById(R.id.firstBrushButton); 51 | 52 | Brush brush = Brushes.get(getApplicationContext())[mCurrentBrushId]; 53 | mFirstBrushButton.setImageResource(brush.iconId); 54 | 55 | mPaintView.setDrawingCacheEnabled(true); 56 | mPaintView.setBrush(brush); 57 | setColor(brush.defaultColor); 58 | mPaintView.setDrawingBgColor(Color.WHITE); 59 | 60 | this.mSizeSeekBar = (PopupSeekBar) findViewById(R.id.sizePopupSeekbar); 61 | this.mSizeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 62 | @Override 63 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 64 | 65 | } 66 | 67 | @Override 68 | public void onStartTrackingTouch(SeekBar seekBar) { 69 | 70 | } 71 | 72 | public void onStopTrackingTouch(SeekBar seekBar) { 73 | setScaledSize(seekBar.getProgress()/100.f); 74 | } 75 | }); 76 | this.mOpacitySeekBar = (PopupSeekBar) findViewById(R.id.opacityPopupSeekbar); 77 | this.mOpacitySeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 78 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 79 | if (fromUser) { 80 | setOpacity(progress/100.f); 81 | } 82 | } 83 | 84 | @Override 85 | public void onStartTrackingTouch(SeekBar seekBar) { 86 | 87 | } 88 | 89 | @Override 90 | public void onStopTrackingTouch(SeekBar seekBar) { 91 | 92 | } 93 | }); 94 | 95 | mSizeSeekBar.setValuePopupWindow(new MySizePopupWindow(this)); 96 | mOpacitySeekBar.setValuePopupWindow(new OpacityPopupWindow(this)); 97 | 98 | setScaledSize(mPaintView.getDrawingScaledSize()); 99 | setOpacity(0.5f); 100 | 101 | findViewById(R.id.currentColorButton).setOnClickListener(new View.OnClickListener() { 102 | @Override 103 | public void onClick(View view) { 104 | HSVColorPickerDialog cpd = new HSVColorPickerDialog( MainActivity.this, mDrawingColor, new HSVColorPickerDialog.OnColorSelectedListener() { 105 | @Override 106 | public void colorSelected(Integer color) { 107 | if(color!=null){ 108 | setColor(color); 109 | } 110 | } 111 | }); 112 | cpd.setTitle(getResources().getString(R.string.dialog_color_title)); 113 | cpd.show(); 114 | } 115 | }); 116 | 117 | findViewById(R.id.firstBrushButton).setOnClickListener(new View.OnClickListener() { 118 | @Override 119 | public void onClick(View view) { 120 | Intent brushSelect = new Intent(MainActivity.this, BrushSelectActivity.class); 121 | brushSelect.putExtra(PaintBrushApp.EXTRA_BRUSH_ID, mCurrentBrushId); 122 | brushSelect.putExtra(PaintBrushApp.EXTRA_BRUSH_TYPE, 0); 123 | startActivityForResult(brushSelect, REQUEST_BRUSH_SELECT); 124 | } 125 | }); 126 | } 127 | 128 | 129 | private void setScaledSize(float scaledSize) { 130 | mSizeSeekBar.setProgress((int) (scaledSize*100.0f)); 131 | mPaintView.setDrawingScaledSize(scaledSize); 132 | } 133 | 134 | private void setOpacity(float opacity) { 135 | this.mOpacitySeekBar.setProgress((int) (opacity*100.0f)); 136 | //this.mColorButton.setColor(getColorWithAlpha(this.mPaintView.getDrawingColor(), opacity)); 137 | this.mPaintView.setDrawingAlpha(opacity); 138 | } 139 | 140 | private void setColor(int color) { 141 | //this.mColorButton.setColor(getColorWithAlpha(color, this.mPaintView.getDrawingAlpha())); 142 | this.mPaintView.setDrawingColor(color); 143 | mDrawingColor = color; 144 | } 145 | 146 | private void setBrush(int brushId){ 147 | Brush[] brushes = Brushes.get(getApplicationContext()); 148 | if(brushId>=0 && brushId= scaledWidth) scaledX = scaledWidth - 1; 287 | for (y = 0; y < h; y++) { 288 | scaledY = y / scale; 289 | if (scaledY >= scaledHeight) scaledY = scaledHeight - 1; 290 | pixels[x * h + y] = scaledPixels[scaledX * scaledHeight + scaledY]; 291 | } 292 | } 293 | 294 | bitmap.setPixels(pixels, 0, w, 0, 0, w, h); 295 | 296 | invalidate(); 297 | } 298 | 299 | @Override 300 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 301 | int maxWidth = MeasureSpec.getSize(widthMeasureSpec); 302 | int maxHeight = MeasureSpec.getSize(heightMeasureSpec); 303 | 304 | int width, height; 305 | /* 306 | * Make the view quadratic, with height and width equal and as large as possible 307 | */ 308 | width = height = Math.min(maxWidth, maxHeight); 309 | 310 | setMeasuredDimension(width, height); 311 | } 312 | 313 | public int getColorForPoint(int x, int y, float[] hsv) { 314 | x -= fullCircleRadius; 315 | y -= fullCircleRadius; 316 | double centerDist = Math.sqrt(x * x + y * y); 317 | hsv[0] = (float) (Math.atan2(y, x) / Math.PI * 180f) + 180; 318 | hsv[1] = Math.max(0f, Math.min(1f, (float) (centerDist / innerCircleRadius))); 319 | return Color.HSVToColor(hsv); 320 | } 321 | 322 | @Override 323 | public boolean onTouchEvent(MotionEvent event) { 324 | int action = event.getActionMasked(); 325 | switch (action) { 326 | case MotionEvent.ACTION_DOWN: 327 | case MotionEvent.ACTION_MOVE: 328 | if (listener != null) { 329 | listener.colorSelected(getColorForPoint((int) event.getX(), (int) event.getY(), colorHsv)); 330 | } 331 | invalidate(); 332 | return true; 333 | } 334 | return super.onTouchEvent(event); 335 | } 336 | 337 | } 338 | 339 | private static class HSVValueSlider extends View { 340 | 341 | public HSVValueSlider(Context context, AttributeSet attrs, int defStyle) { 342 | super(context, attrs, defStyle); 343 | } 344 | 345 | public HSVValueSlider(Context context, AttributeSet attrs) { 346 | super(context, attrs); 347 | } 348 | 349 | public HSVValueSlider(Context context) { 350 | super(context); 351 | } 352 | 353 | private OnColorSelectedListener listener; 354 | 355 | public void setListener(OnColorSelectedListener listener) { 356 | this.listener = listener; 357 | } 358 | 359 | float[] colorHsv = {0f, 0f, 1f}; 360 | 361 | public void setColor(int color, boolean keepValue) { 362 | float oldValue = colorHsv[2]; 363 | Color.colorToHSV(color, colorHsv); 364 | if (keepValue) { 365 | colorHsv[2] = oldValue; 366 | } 367 | if (listener != null) { 368 | listener.colorSelected(Color.HSVToColor(colorHsv)); 369 | } 370 | 371 | createBitmap(); 372 | } 373 | 374 | @Override 375 | protected void onDraw(Canvas canvas) { 376 | if (bitmap != null) { 377 | canvas.drawBitmap(bitmap, srcRect, dstRect, null); 378 | } 379 | } 380 | 381 | private Rect srcRect; 382 | private Rect dstRect; 383 | private Bitmap bitmap; 384 | private int[] pixels; 385 | 386 | @Override 387 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 388 | super.onSizeChanged(w, h, oldw, oldh); 389 | 390 | srcRect = new Rect(0, 0, w, 1); 391 | dstRect = new Rect(0, 0, w, h); 392 | bitmap = Bitmap.createBitmap(w, 1, Config.ARGB_8888); 393 | pixels = new int[w]; 394 | 395 | createBitmap(); 396 | } 397 | 398 | private void createBitmap() { 399 | if (bitmap == null) { 400 | return; 401 | } 402 | int w = getWidth(); 403 | 404 | float[] hsv = new float[]{colorHsv[0], colorHsv[1], 1f}; 405 | 406 | int selectedX = (int) (colorHsv[2] * w); 407 | 408 | float value = 0; 409 | float valueStep = 1f / w; 410 | for (int x = 0; x < w; x++) { 411 | value += valueStep; 412 | if (x >= selectedX - 1 && x <= selectedX + 1) { 413 | int intVal = 0xFF - (int) (value * 0xFF); 414 | int color = intVal * 0x010101 + 0xFF000000; 415 | pixels[x] = color; 416 | } else { 417 | hsv[2] = value; 418 | pixels[x] = Color.HSVToColor(hsv); 419 | } 420 | } 421 | 422 | bitmap.setPixels(pixels, 0, w, 0, 0, w, 1); 423 | 424 | invalidate(); 425 | } 426 | 427 | @Override 428 | public boolean onTouchEvent(MotionEvent event) { 429 | int action = event.getActionMasked(); 430 | switch (action) { 431 | case MotionEvent.ACTION_DOWN: 432 | case MotionEvent.ACTION_MOVE: 433 | int x = Math.max(0, Math.min(bitmap.getWidth() - 1, (int) event.getX())); 434 | float value = x / (float) bitmap.getWidth(); 435 | if (colorHsv[2] != value) { 436 | colorHsv[2] = value; 437 | if (listener != null) { 438 | listener.colorSelected(Color.HSVToColor(colorHsv)); 439 | } 440 | createBitmap(); 441 | invalidate(); 442 | } 443 | return true; 444 | } 445 | return super.onTouchEvent(event); 446 | } 447 | 448 | } 449 | 450 | /** 451 | * Generate a value suitable for use in {setId(int)}. 452 | * This value will not collide with ID values generated at build time by aapt for R.id. 453 | * 454 | * @return a generated ID value 455 | */ 456 | public static int generateViewId() { 457 | for (; ; ) { 458 | final int result = sNextGeneratedId.get(); 459 | // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 460 | int newValue = result + 1; 461 | if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. 462 | if (sNextGeneratedId.compareAndSet(result, newValue)) { 463 | return result; 464 | } 465 | } 466 | } 467 | } 468 | -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/drawing/Brush.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.drawing; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.Log; 6 | 7 | import it.moondroid.paintbrush.R; 8 | 9 | /** 10 | * Created by marco.granatiero on 07/08/2014. 11 | */ 12 | public class Brush { 13 | 14 | private static int[] BRUSH_MASK_IMAGE_ARRAY_STYLEABLE = null; 15 | public static final int BRUSH_TYPE_PHOTO = 1; 16 | public static final int BRUSH_TYPE_STYLISH = 0; 17 | public static final int COLORING_TYPE_NORMAL = 0; 18 | public static final int COLORING_TYPE_REF_IMAGE_ALL_TIME = 1; 19 | public static final int COLORING_TYPE_REF_IMAGE_INIT_TIME = 2; 20 | private static final String TAG = "Brush"; 21 | public float angle; 22 | public float angleJitter; 23 | public int autoStrokeCount; 24 | public float autoStrokeDistribution; 25 | public float autoStrokeJointPitch; 26 | public int autoStrokeLength; 27 | public float autoStrokeStraight; 28 | public float colorPatchAlpha; 29 | public int coloringType; 30 | public int defaultColor; 31 | public String icon; 32 | public int iconId; 33 | public final int id; 34 | public boolean isEraser; 35 | public float jitterBrightness; 36 | public float jitterHue; 37 | public float jitterSaturation; 38 | public float lineEndAlphaScale; 39 | public int lineEndFadeLength; 40 | public float lineEndSizeScale; 41 | public float lineEndSpeedLength; 42 | public int lineTaperFadeLength; 43 | public int lineTaperStartLength; 44 | public String[] maskImageArray; 45 | public int[] maskImageIdArray; 46 | public float maxSize; 47 | public float minSize; 48 | public String name; 49 | public String preview; 50 | public int previewId; 51 | public float size; 52 | public float smudgingPatchAlpha; 53 | public float spacing; 54 | public float spread; 55 | public float textureDepth; 56 | public boolean traceMode; 57 | public boolean useDeviceAngle; 58 | public boolean useFirstJitter; 59 | public boolean useFlowingAngle; 60 | public boolean useSmudging; 61 | public boolean useSingleLayerStroke; 62 | 63 | static { 64 | BRUSH_MASK_IMAGE_ARRAY_STYLEABLE = new int[]{R.styleable.Brush_maskImageArray0, 65 | R.styleable.Brush_maskImageArray1, R.styleable.Brush_maskImageArray2, 66 | R.styleable.Brush_maskImageArray3, R.styleable.Brush_maskImageArray4, 67 | R.styleable.Brush_maskImageArray5, R.styleable.Brush_maskImageArray6, 68 | R.styleable.Brush_maskImageArray7, R.styleable.Brush_maskImageArray8, 69 | R.styleable.Brush_maskImageArray9}; 70 | } 71 | 72 | public Brush(int id) { 73 | this.id = id; 74 | } 75 | 76 | private void loadFromTypedArray(TypedArray a) { 77 | this.angle = a.getFloat(R.styleable.Brush_angle, 0.0f); 78 | this.angleJitter = a.getFloat(R.styleable.Brush_angleJitter, 0.0f); 79 | this.autoStrokeCount = a.getInt(R.styleable.Brush_autoStrokeCount, 0); 80 | this.autoStrokeDistribution = a.getFloat(R.styleable.Brush_autoStrokeDistribution, 0.0f); 81 | this.autoStrokeJointPitch = a.getFloat(R.styleable.Brush_autoStrokeJointPitch, 0.0f); 82 | this.autoStrokeLength = a.getInt(R.styleable.Brush_autoStrokeLength, 1); 83 | this.autoStrokeStraight = a.getFloat(R.styleable.Brush_autoStrokeStraight, 0.0f); 84 | this.colorPatchAlpha = a.getFloat(R.styleable.Brush_colorPatchAlpha, 0.0f); 85 | this.coloringType = a.getInt(R.styleable.Brush_coloringType, COLORING_TYPE_NORMAL); 86 | this.iconId = a.getResourceId(R.styleable.Brush_icon, 0); 87 | this.isEraser = a.getBoolean(R.styleable.Brush_isEraser, false); 88 | this.jitterBrightness = a.getFloat(R.styleable.Brush_jitterBrightness, 0.0f); 89 | this.jitterHue = a.getFloat(R.styleable.Brush_jitterHue, 0.0f); 90 | this.jitterSaturation = a.getFloat(R.styleable.Brush_jitterSaturation, 0.0f); 91 | this.lineEndAlphaScale = a.getFloat(R.styleable.Brush_lineEndAlphaScale, 0.0f); 92 | this.lineEndFadeLength = a.getInt(R.styleable.Brush_lineEndFadeLength, 0); 93 | this.lineEndSizeScale = a.getFloat(R.styleable.Brush_lineEndSizeScale, 0.0f); 94 | this.lineEndSpeedLength = a.getFloat(R.styleable.Brush_lineEndSpeedLength, 0.0f); 95 | this.lineTaperFadeLength = a.getInt(R.styleable.Brush_lineTaperFadeLength, 0); 96 | this.lineTaperStartLength = a.getInt(R.styleable.Brush_lineTaperStartLength, 0); 97 | int i = COLORING_TYPE_NORMAL; 98 | while (i < BRUSH_MASK_IMAGE_ARRAY_STYLEABLE.length && a.getResourceId(BRUSH_MASK_IMAGE_ARRAY_STYLEABLE[i], 0) != 0) { 99 | i++; 100 | } 101 | this.maskImageIdArray = new int[i]; 102 | i = 0; 103 | while (i < this.maskImageIdArray.length) { 104 | this.maskImageIdArray[i] = a.getResourceId(BRUSH_MASK_IMAGE_ARRAY_STYLEABLE[i], 0); 105 | i++; 106 | } 107 | this.maxSize = a.getDimension(R.styleable.Brush_maxSize, 0.0f); 108 | this.minSize = a.getDimension(R.styleable.Brush_minSize, 0.0f); 109 | this.name = a.getString(R.styleable.Brush_name); 110 | this.previewId = a.getResourceId(R.styleable.Brush_preview, 0); 111 | this.size = a.getDimension(R.styleable.Brush_size, 0.0f); 112 | this.smudgingPatchAlpha = a.getFloat(R.styleable.Brush_smudgingPatchAlpha, 0.0f); 113 | this.spacing = a.getFloat(R.styleable.Brush_spacing, 0.0f); 114 | this.spread = a.getFloat(R.styleable.Brush_spread, 0.0f); 115 | this.textureDepth = a.getFloat(R.styleable.Brush_textureDepth, 0.0f); 116 | this.traceMode = a.getBoolean(R.styleable.Brush_traceMode, false); 117 | this.useDeviceAngle = a.getBoolean(R.styleable.Brush_useDeviceAngle, false); 118 | this.useFirstJitter = a.getBoolean(R.styleable.Brush_useFirstJitter, false); 119 | this.useFlowingAngle = a.getBoolean(R.styleable.Brush_useFlowingAngle, false); 120 | this.useSmudging = a.getBoolean(R.styleable.Brush_useSmudging, false); 121 | this.useSingleLayerStroke = a.getBoolean(R.styleable.Brush_useSingleLayerStroke, false); 122 | this.defaultColor = a.getColor(R.styleable.Brush_defaultColor, 0); 123 | } 124 | 125 | public static Brush[] parseStyleData(Context context, int[] styleArray) { 126 | Brush[] brushes = new Brush[styleArray.length]; 127 | int i = 0; 128 | while (i < brushes.length) { 129 | Brush brush = new Brush(i); 130 | TypedArray a = context.obtainStyledAttributes(styleArray[i], R.styleable.Brush); 131 | brush.loadFromTypedArray(a); 132 | a.recycle(); 133 | brushes[i] = brush; 134 | i++; 135 | } 136 | return brushes; 137 | } 138 | 139 | public int getBrushType() { 140 | return this.coloringType == 0 ? COLORING_TYPE_NORMAL : COLORING_TYPE_REF_IMAGE_ALL_TIME; 141 | } 142 | 143 | public float getScaledSize() { 144 | return (this.size - this.minSize) / (this.maxSize - this.minSize); 145 | } 146 | 147 | public float getSizeFromScaledSize(float scaledSize) { 148 | return this.minSize + (this.maxSize - this.minSize) * scaledSize; 149 | } 150 | 151 | public boolean setScaledSize(float scaledSize) { 152 | if (scaledSize < 0.0f) { 153 | scaledSize = 0.0f; 154 | } else if (scaledSize > 1.0f) { 155 | scaledSize = 1.0f; 156 | } 157 | float newSize = getSizeFromScaledSize(scaledSize); 158 | if (this.size == newSize) { 159 | return false; 160 | } 161 | this.size = newSize; 162 | return true; 163 | } 164 | 165 | public String toString() { 166 | return "Brush " + this.angle + ", " + this.angleJitter + ", " + this.autoStrokeCount + ", " + this.name + ", " + this.isEraser + ", " + this.maskImageIdArray.length + ", " + (this.maskImageIdArray.length == 1 ? Integer.valueOf(this.maskImageIdArray[0]) : this.maskImageIdArray[0] + "/" + this.maskImageIdArray[1]); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/drawing/Brushes.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.drawing; 2 | 3 | import android.content.Context; 4 | import android.os.SystemClock; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import it.moondroid.paintbrush.R; 10 | 11 | 12 | public class Brushes { 13 | private static int[] BRUSH_STYLES; 14 | private static Brush[] mBrushList; 15 | private static List mPhotoBrushList; 16 | private static List mStylishBrushList; 17 | 18 | static { 19 | mStylishBrushList = new ArrayList(); 20 | mPhotoBrushList = new ArrayList(); 21 | BRUSH_STYLES = new int[]{R.style.Brush_Bamboo1, R.style.Brush_Bamboo2, R.style.Brush_AirBrush, 22 | R.style.Brush_Pen, R.style.Brush_Calligraphy, R.style.Brush_HardPencil, 23 | R.style.Brush_SoftPencil, R.style.Brush_InkPen, R.style.Brush_BallpointPen, 24 | R.style.Brush_HardEraser, R.style.Brush_SoftEraser, 25 | R.style.Brush_AirBrush, R.style.Brush_Oil, R.style.Brush_FeltPen, 26 | R.style.Brush_WaterColor, R.style.Brush_OilPastel, R.style.Brush_Pastel, 27 | R.style.Brush_HardPastel, R.style.Brush_Creyon, 28 | R.style.Brush_Knife1, R.style.Brush_CombKnife, R.style.Brush_ColorlessOil, 29 | R.style.Brush_Finger, R.style.Brush_InkSpot, 30 | R.style.Brush_Flowers, R.style.Brush_Fish, R.style.Brush_Sponge}; 31 | } 32 | 33 | public static List get(Context context, int type) { 34 | if (mBrushList == null) { 35 | loadBrushList(context); 36 | } 37 | return type == 0 ? mStylishBrushList : mPhotoBrushList; 38 | } 39 | 40 | public static Brush[] get(Context context) { 41 | if (mBrushList == null) { 42 | loadBrushList(context); 43 | } 44 | return mBrushList; 45 | } 46 | 47 | public static final void loadBrushList(Context context) { 48 | if (mBrushList == null) { 49 | long t1 = SystemClock.elapsedRealtime(); 50 | mBrushList = Brush.parseStyleData(context, BRUSH_STYLES); 51 | long t2 = SystemClock.elapsedRealtime(); 52 | Brush[] arr$ = mBrushList; 53 | int len$ = arr$.length; 54 | int i$ = 0; 55 | while (i$ < len$) { 56 | Brush brush = arr$[i$]; 57 | if (brush.getBrushType() == 0) { 58 | mStylishBrushList.add(brush); 59 | } else { 60 | mPhotoBrushList.add(brush); 61 | } 62 | i$++; 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/drawing/DrawingView.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.drawing; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.RectF; 9 | import android.util.AttributeSet; 10 | import android.util.Log; 11 | import android.view.MotionEvent; 12 | import android.view.View; 13 | 14 | /** 15 | * Created by marco.granatiero on 07/08/2014. 16 | */ 17 | 18 | public class DrawingView extends View { 19 | 20 | public enum MotionMode { 21 | DRAW_POLY 22 | } 23 | 24 | private static final float STROKE_WIDTH = 20.0f; 25 | 26 | /** Need to track this so the dirty region can accommodate the stroke. **/ 27 | private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2; 28 | 29 | private Paint paint = new Paint(); 30 | private Path path = new Path(); 31 | 32 | /** 33 | * Optimizes painting by invalidating the smallest possible area. 34 | */ 35 | private float lastTouchX; 36 | private float lastTouchY; 37 | private final RectF dirtyRect = new RectF(); 38 | 39 | // final OnTouchListener selectionAndMoveListener = // not shown; 40 | // 41 | // final OnTouchListener drawRectangleListener = // not shown; 42 | // 43 | // final OnTouchListener drawOvalListener = // not shown; 44 | 45 | final OnTouchListener drawPolyLineListener = new OnTouchListener() { 46 | 47 | @Override 48 | public boolean onTouch(View v, MotionEvent event) { 49 | // Log.d("jabagator", "onTouch: " + event); 50 | float eventX = event.getX(); 51 | float eventY = event.getY(); 52 | 53 | switch (event.getAction()) { 54 | case MotionEvent.ACTION_DOWN: 55 | path.moveTo(eventX, eventY); 56 | lastTouchX = eventX; 57 | lastTouchY = eventY; 58 | // No end point yet, so don't waste cycles invalidating. 59 | return true; 60 | 61 | case MotionEvent.ACTION_MOVE: 62 | case MotionEvent.ACTION_UP: 63 | // Start tracking the dirty region. 64 | resetDirtyRect(eventX, eventY); 65 | 66 | // When the hardware tracks events faster than 67 | // they can be delivered to the app, the 68 | // event will contain a history of those skipped points. 69 | int historySize = event.getHistorySize(); 70 | for (int i = 0; i < historySize; i++) { 71 | float historicalX = event.getHistoricalX(i); 72 | float historicalY = event.getHistoricalY(i); 73 | expandDirtyRect(historicalX, historicalY); 74 | path.lineTo(historicalX, historicalY); 75 | } 76 | 77 | // After replaying history, connect the line to the touch point. 78 | path.lineTo(eventX, eventY); 79 | break; 80 | 81 | default: 82 | Log.d("jabagator", "Unknown touch event " + event.toString()); 83 | return false; 84 | } 85 | 86 | // Include half the stroke width to avoid clipping. 87 | invalidate( 88 | (int) (dirtyRect.left - HALF_STROKE_WIDTH), 89 | (int) (dirtyRect.top - HALF_STROKE_WIDTH), 90 | (int) (dirtyRect.right + HALF_STROKE_WIDTH), 91 | (int) (dirtyRect.bottom + HALF_STROKE_WIDTH)); 92 | 93 | lastTouchX = eventX; 94 | lastTouchY = eventY; 95 | 96 | return true; 97 | } 98 | 99 | /** 100 | * Called when replaying history to ensure the dirty region 101 | * includes all points. 102 | */ 103 | private void expandDirtyRect(float historicalX, float historicalY) { 104 | if (historicalX < dirtyRect.left) { 105 | dirtyRect.left = historicalX; 106 | } else if (historicalX > dirtyRect.right) { 107 | dirtyRect.right = historicalX; 108 | } 109 | if (historicalY < dirtyRect.top) { 110 | dirtyRect.top = historicalY; 111 | } else if (historicalY > dirtyRect.bottom) { 112 | dirtyRect.bottom = historicalY; 113 | } 114 | } 115 | 116 | /** 117 | * Resets the dirty region when the motion event occurs. 118 | */ 119 | private void resetDirtyRect(float eventX, float eventY) { 120 | 121 | // The lastTouchX and lastTouchY were set when the ACTION_DOWN 122 | // motion event occurred. 123 | dirtyRect.left = Math.min(lastTouchX, eventX); 124 | dirtyRect.right = Math.max(lastTouchX, eventX); 125 | dirtyRect.top = Math.min(lastTouchY, eventY); 126 | dirtyRect.bottom = Math.max(lastTouchY, eventY); 127 | } 128 | }; 129 | 130 | /** DrawingView Constructor */ 131 | public DrawingView(Context context, AttributeSet attrs) { 132 | super(context, attrs); 133 | 134 | paint.setAntiAlias(true); 135 | paint.setColor(Color.BLACK); 136 | paint.setStyle(Paint.Style.STROKE); 137 | paint.setStrokeJoin(Paint.Join.ROUND); 138 | paint.setStrokeWidth(STROKE_WIDTH); 139 | 140 | setMode(MotionMode.DRAW_POLY); 141 | } 142 | 143 | public void clear() { 144 | path.reset(); 145 | 146 | // Repaints the entire view. 147 | invalidate(); 148 | } 149 | 150 | @Override 151 | protected void onDraw(Canvas canvas) { 152 | canvas.drawPath(path, paint); 153 | } 154 | 155 | /** 156 | * Sets the DrawingView into one of several modes, such 157 | * as "select" mode (e.g., for moving or resizeing objects), 158 | * or "Draw polyline" (smooth curve), "draw rectangle", etc. 159 | */ 160 | private void setMode(MotionMode motionMode) { 161 | switch(motionMode) { 162 | // case SELECT_AND_MOVE: 163 | // setOnTouchListener(selectionAndMoveListener); 164 | // break; 165 | case DRAW_POLY: 166 | setOnTouchListener(drawPolyLineListener); 167 | break; 168 | // case DRAW_RECTANGLE: 169 | // setOnTouchListener(drawRectangleListener); 170 | // break; 171 | // case DRAW_OVAL: 172 | // setOnTouchListener(drawOvalListener); 173 | // break; 174 | default: 175 | throw new IllegalStateException("Unknown MotionMode " + motionMode); 176 | } 177 | } 178 | } -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/drawing/PaintView.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.drawing; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.Canvas; 8 | import android.graphics.Color; 9 | import android.graphics.Matrix; 10 | import android.graphics.Paint; 11 | import android.graphics.PointF; 12 | import android.graphics.PorterDuff; 13 | import android.graphics.PorterDuffXfermode; 14 | import android.graphics.Rect; 15 | import android.graphics.RectF; 16 | import android.graphics.Shader; 17 | import android.graphics.drawable.BitmapDrawable; 18 | import android.os.Build; 19 | import android.util.AttributeSet; 20 | import android.util.FloatMath; 21 | import android.util.Log; 22 | import android.view.MotionEvent; 23 | import android.view.View; 24 | 25 | import java.util.Random; 26 | 27 | import it.moondroid.paintbrush.R; 28 | 29 | /** 30 | * Created by marco.granatiero on 07/08/2014. 31 | */ 32 | public class PaintView extends View { 33 | 34 | private static final float STROKE_WIDTH = 20.0f; 35 | 36 | private Brush mBrush; 37 | private int mColor; 38 | private int mLineColor; 39 | private float mDrawingAlpha; 40 | private int mBackgroundLayerColor; 41 | 42 | private float mLastDrawDistance; 43 | private float mSpacing; 44 | 45 | private Bitmap mDrawingLayer; 46 | private Canvas mDrawingLayerCanvas; 47 | private Rect mOnDrawCanvasRect; 48 | private Bitmap mPathLayer; 49 | private Canvas mPathLayerCanvas; 50 | private float mPathWidth; 51 | private float mPathWidthHalf; 52 | private Bitmap mMergedLayer; 53 | private Canvas mMergedLayerCanvas; 54 | private Bitmap mTextureLayer; 55 | private Canvas mTextureLayerCanvas; 56 | private BitmapDrawable mTextureDrawable; 57 | private Bitmap mTempPathLayer; 58 | private Canvas mTempPathLayerCanvas; 59 | 60 | private RectF mLineDirtyRect; 61 | private RectF mDirtyRect; 62 | 63 | private Paint mNormalPaint; 64 | private Paint mSrcPaint; 65 | private Paint mDstInPaint; 66 | private Paint mDstOutPaint; 67 | 68 | private OnTouchHandler mCurveDrawingHandler; 69 | private TouchResampler mTouchResampler; 70 | private float mMaxVelocityScale; 71 | private static float VELOCITY_MAX_SCALE = 130.0f; 72 | private static final Bitmap EMPTY_BITMAP = Build.VERSION.SDK_INT < 14 ? Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) : null; 73 | 74 | private Bitmap[] mMaskBitmap; 75 | private int mMaskPadding; 76 | 77 | private Random mRandom; 78 | private Matrix mMatrix; 79 | private float mDeviceAngle; 80 | private PointF mOldPt; 81 | private boolean mIsJitterColor; 82 | 83 | private boolean mDrawingLayerNeedDrawn; 84 | private boolean mIsBatchDraw; 85 | 86 | private static interface OnTouchHandler { 87 | boolean onTouchEvent(int i, MotionEvent motionEvent); 88 | } 89 | 90 | 91 | public PaintView(Context context, AttributeSet attrs) { 92 | super(context, attrs); 93 | 94 | this.mTextureDrawable = new BitmapDrawable(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.texture01)); 95 | this.mTextureDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 96 | 97 | mNormalPaint = new Paint(Paint.FILTER_BITMAP_FLAG); 98 | mSrcPaint = new Paint(Paint.FILTER_BITMAP_FLAG); 99 | mDstInPaint = new Paint(Paint.FILTER_BITMAP_FLAG); 100 | mDstOutPaint = new Paint(Paint.FILTER_BITMAP_FLAG); 101 | 102 | // mNormalPaint.setAntiAlias(true); 103 | // mNormalPaint.setColor(Color.BLACK); 104 | // paint.setStyle(Paint.Style.STROKE); 105 | // paint.setStrokeJoin(Paint.Join.ROUND); 106 | // paint.setStrokeWidth(STROKE_WIDTH); 107 | 108 | mDrawingLayerCanvas = new Canvas(); 109 | mPathLayerCanvas = new Canvas(); 110 | this.mMergedLayerCanvas = new Canvas(); 111 | this.mTextureLayerCanvas = new Canvas(); 112 | this.mTempPathLayerCanvas = new Canvas(); 113 | 114 | mOnDrawCanvasRect = new Rect(); 115 | mLineDirtyRect = new RectF(); 116 | mDirtyRect = new RectF(); 117 | 118 | mDrawingAlpha = 1.0f; 119 | 120 | mSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); 121 | mDstInPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); 122 | mDstOutPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 123 | 124 | this.mCurveDrawingHandler = new OnTouchHandler() { 125 | public boolean onTouchEvent(int action, MotionEvent event) { 126 | if (!PaintView.this.mBrush.traceMode) { 127 | mTouchResampler.onTouchEvent(event); 128 | return true; 129 | } 130 | return false; 131 | } 132 | }; 133 | 134 | this.mTouchResampler = new MyTouchDistanceResampler(); 135 | 136 | mRandom = new Random(); 137 | mMatrix = new Matrix(); 138 | mOldPt = new PointF(); 139 | 140 | } 141 | 142 | public void setBrush(Brush brush) { 143 | mBrush = brush; 144 | 145 | mPathWidth = brush.size; 146 | mPathWidthHalf = brush.size / 2.0f; 147 | 148 | mSpacing = brush.spacing * brush.size; 149 | 150 | releaseBrushSizeBitmaps(); 151 | 152 | mPathLayer = Bitmap.createBitmap((int) mPathWidth, (int) mPathWidth, Bitmap.Config.ARGB_8888); 153 | mPathLayerCanvas.setBitmap(this.mPathLayer); 154 | 155 | mMaxVelocityScale = (brush.size * brush.lineEndSpeedLength) / VELOCITY_MAX_SCALE; 156 | 157 | this.mMaskBitmap = new Bitmap[brush.maskImageIdArray.length]; 158 | this.mMaskPadding = (int) (this.mPathWidth / 3.5f); 159 | int i = 0; 160 | while (i < this.mMaskBitmap.length) { 161 | this.mMaskBitmap[i] = decodeScaledExpandResource(getResources(), brush.maskImageIdArray[i], (int) this.mPathWidth, (int) this.mPathWidth, this.mMaskPadding); 162 | i++; 163 | } 164 | 165 | if (((double) brush.jitterHue) == 0.0d && ((double) brush.jitterSaturation) == 0.0d && ((double) brush.jitterBrightness) == 0.0d) { 166 | mIsJitterColor = false; 167 | } else { 168 | mIsJitterColor = true; 169 | } 170 | 171 | this.mTempPathLayer = Bitmap.createBitmap((int) this.mPathWidth, (int) this.mPathWidth, Bitmap.Config.ARGB_8888); 172 | this.mTempPathLayerCanvas.setBitmap(this.mTempPathLayer); 173 | 174 | } 175 | 176 | private static Bitmap decodeScaledExpandResource(Resources res, int id, int width, int height, int padding) { 177 | Bitmap src = BitmapFactory.decodeResource(res, id); 178 | if (src == null) { 179 | return null; 180 | } 181 | Bitmap dst = Bitmap.createBitmap(padding * 2 + width, padding * 2 + height, Bitmap.Config.ARGB_8888); 182 | Canvas c = new Canvas(dst); 183 | c.drawBitmap(src, new Rect(0, 0, src.getWidth(), src.getHeight()), new Rect(padding, padding, padding + width, padding + height), null); 184 | c.setBitmap(EMPTY_BITMAP); 185 | if (src == dst) { 186 | return dst; 187 | } 188 | src.recycle(); 189 | return dst; 190 | } 191 | 192 | 193 | 194 | public Brush getBrush() { 195 | return mBrush; 196 | } 197 | 198 | 199 | public void setDrawingColor(int color) { 200 | mColor = color; 201 | } 202 | 203 | public void setDrawingBgColor(int color) { 204 | this.mBackgroundLayerColor = color; 205 | invalidate(); 206 | } 207 | 208 | public float getDrawingScaledSize() { 209 | return mBrush.getScaledSize(); 210 | } 211 | 212 | public void setDrawingScaledSize(float scaledSize) { 213 | if (mBrush.setScaledSize(scaledSize)) { 214 | setBrush(mBrush); 215 | } 216 | } 217 | 218 | public void setDrawingAlpha(float alpha) { 219 | this.mDrawingAlpha = alpha; 220 | } 221 | 222 | public float getDrawingAlpha() { 223 | return this.mDrawingAlpha; 224 | } 225 | 226 | 227 | public boolean isClear() { 228 | //return (this.mBitmapHistoryManager.isEmpty() && this.mBackgroundBitmap == null) ? true : false; 229 | return false; 230 | } 231 | 232 | public void clear() { 233 | setDrawingForegroundBitmap(null); 234 | //setDrawingBackgroundBitmap(null); 235 | } 236 | 237 | public void setDrawingForegroundBitmap(Bitmap bitmap) { 238 | this.mDrawingLayerCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC); 239 | this.mMergedLayerCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC); 240 | 241 | invalidate(); 242 | } 243 | 244 | public Bitmap getForegroundBitmap() { 245 | return this.mMergedLayer; 246 | } 247 | 248 | @Override 249 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 250 | super.onSizeChanged(w, h, oldw, oldh); 251 | 252 | releaseViewSizeBitmaps(); 253 | 254 | mDrawingLayer = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 255 | mDrawingLayerCanvas.setBitmap(mDrawingLayer); 256 | this.mMergedLayer = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 257 | this.mMergedLayerCanvas.setBitmap(this.mMergedLayer); 258 | this.mTextureLayer = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8); 259 | this.mTextureLayerCanvas.setBitmap(this.mTextureLayer); 260 | this.mTextureDrawable.setBounds(0, 0, w, h); 261 | this.mTextureDrawable.draw(this.mTextureLayerCanvas); 262 | 263 | } 264 | 265 | @Override 266 | public boolean onTouchEvent(MotionEvent event) { 267 | this.mIsBatchDraw = false; 268 | 269 | if (this.mBrush == null) { 270 | return super.onTouchEvent(event); 271 | } 272 | int action = Build.VERSION.SDK_INT >= 8 ? event.getActionMasked() : event.getAction() & 255; 273 | 274 | if (this.mCurveDrawingHandler != null) { 275 | return this.mCurveDrawingHandler.onTouchEvent(action, event); 276 | } 277 | 278 | return false; 279 | 280 | } 281 | 282 | 283 | @Override 284 | protected void onDraw(Canvas canvas) { 285 | super.onDraw(canvas); 286 | 287 | canvas.save(); 288 | canvas.getClipBounds(this.mOnDrawCanvasRect); 289 | drawToCanvas(canvas, mOnDrawCanvasRect); 290 | canvas.restore(); 291 | 292 | invalidate(mOnDrawCanvasRect); 293 | } 294 | 295 | private void drawToCanvas(Canvas canvas, Rect rect) { 296 | canvas.drawColor(mBackgroundLayerColor, PorterDuff.Mode.SRC); 297 | 298 | if (rect == null) { 299 | canvas.saveLayer(null, null, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); 300 | } else { 301 | canvas.saveLayer((float) (rect.left - 1), (float) (this.mOnDrawCanvasRect.top - 1), 302 | (float) (this.mOnDrawCanvasRect.right + 1), (float) (this.mOnDrawCanvasRect.bottom + 1), 303 | null, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); 304 | } 305 | 306 | if(mBrush.useSingleLayerStroke){ 307 | canvas.drawBitmap(this.mMergedLayer, 0.0f, 0.0f, this.mSrcPaint); 308 | if ((!this.mDrawingLayerNeedDrawn)) { 309 | canvas.restore(); 310 | }else { 311 | Paint p; 312 | p = !(this.mBrush.isEraser) ? this.mNormalPaint : this.mDstOutPaint; 313 | p.setAlpha((int) (this.mDrawingAlpha * 255.0f)); 314 | canvas.drawBitmap(mDrawingLayer, 0.0f, 0.0f, p); 315 | canvas.restore(); 316 | } 317 | }else{ 318 | 319 | canvas.drawBitmap(this.mMergedLayer, 0.0f, 0.0f, this.mSrcPaint); 320 | if ((this.mDrawingLayerNeedDrawn)) { 321 | Paint p; 322 | p = !(this.mBrush.isEraser) ? this.mNormalPaint : this.mDstOutPaint; 323 | canvas.drawBitmap(mDrawingLayer, 0.0f, 0.0f, p); 324 | } 325 | canvas.restore(); 326 | } 327 | 328 | } 329 | 330 | private void moveToThread(float x, float y) { 331 | float level = 1.0f; 332 | resetDrawingDirtyRect(); 333 | moveToAction(x, y, level); 334 | } 335 | 336 | private void moveToAction(float x, float y, float level) { 337 | 338 | mOldPt.set(x, y); 339 | 340 | beforeLine(x, y); 341 | } 342 | 343 | 344 | private void beforeLine(float x, float y) { 345 | Brush brush = mBrush; 346 | mLineColor = mColor; 347 | } 348 | 349 | private void addSpot(float x, float y, float tipScale, float tipAlpha) { 350 | float drawX = x; 351 | float drawY = y; 352 | Brush brush = mBrush; 353 | 354 | if (brush.spread > 0.0f) { 355 | float spreadAngle = this.mRandom.nextFloat() * 6.2831855f; 356 | drawX += (FloatMath.cos(spreadAngle) * brush.spread) * brush.size; 357 | drawY += (FloatMath.sin(spreadAngle) * brush.spread) * brush.size; 358 | } 359 | 360 | fillBrushWithColor(brush, drawX, drawY, tipAlpha); 361 | if (brush.useSmudging) { 362 | smudgingBrush(brush, this.mOldPt.x - this.mPathWidthHalf, this.mOldPt.y - this.mPathWidthHalf, tipAlpha); 363 | } 364 | maskBrushWithAngle(brush, getBrushSpotAngle(brush, this.mOldPt.x, this.mOldPt.y, x, y), tipAlpha); 365 | if (brush.textureDepth > 0.0f) { 366 | textureBrush(brush, drawX - this.mPathWidthHalf, drawY - this.mPathWidthHalf); 367 | } 368 | drawBrushWithScale(drawX, drawY, tipScale); 369 | 370 | mOldPt.set(x, y); 371 | mDirtyRect.union(drawX - this.mPathWidthHalf, drawY - this.mPathWidthHalf, 372 | this.mPathWidthHalf + drawX, this.mPathWidthHalf + drawY); 373 | 374 | } 375 | 376 | private void fillBrushWithColor(Brush brush, float x, float y, float tipAlpha) { 377 | //int color = mLineColor; 378 | int color; 379 | float drawingAlpha; 380 | 381 | if(mBrush.useSingleLayerStroke){ 382 | drawingAlpha = 1.0f; 383 | }else { 384 | drawingAlpha = mDrawingAlpha; 385 | } 386 | 387 | if ((!this.mIsJitterColor) || brush.useFirstJitter) { 388 | color = Color.argb((int) ((drawingAlpha * brush.colorPatchAlpha * tipAlpha) * 255.0f), Color.red(mLineColor), Color.green(mLineColor), Color.blue(mLineColor)); 389 | } else { 390 | int jitterColor = jitterColor(this.mLineColor); 391 | color = Color.argb((int) (drawingAlpha * tipAlpha * 255.0f), Color.red(jitterColor), Color.green(jitterColor), Color.blue(jitterColor)); 392 | } 393 | 394 | mPathLayerCanvas.drawColor(color, PorterDuff.Mode.SRC); 395 | 396 | } 397 | 398 | private void maskBrushWithAngle(Brush brush, float angle, float tipAlpha) { 399 | 400 | mDstInPaint.setAlpha((int) ((tipAlpha * tipAlpha) * 255.0f)); 401 | 402 | Bitmap maskLayer = this.mMaskBitmap.length == 1 ? this.mMaskBitmap[0] : this.mMaskBitmap[this.mRandom.nextInt(this.mMaskBitmap.length)]; 403 | 404 | if (angle != 0.0f) { 405 | this.mMatrix.setTranslate((float) (-mMaskPadding), (float) (-mMaskPadding)); 406 | this.mMatrix.postRotate((float) Math.toDegrees((double) angle), this.mPathWidthHalf, this.mPathWidthHalf); 407 | mPathLayerCanvas.drawBitmap(maskLayer, this.mMatrix, mDstInPaint); 408 | }else{ 409 | mPathLayerCanvas.drawBitmap(maskLayer, (float) (-mMaskPadding), (float) (-mMaskPadding), mDstInPaint); 410 | } 411 | 412 | 413 | } 414 | 415 | private void destLineThread() { 416 | if (this.mBrush.isEraser) { 417 | mergeWithAlpha(this.mDrawingAlpha, this.mDstOutPaint, this.mLineDirtyRect); 418 | } else { 419 | mergeWithAlpha(this.mDrawingAlpha, this.mNormalPaint, this.mLineDirtyRect); 420 | } 421 | } 422 | 423 | private void mergeWithAlpha(float alpha, Paint paint, RectF rectF) { 424 | if(mBrush.useSingleLayerStroke){ 425 | paint.setAlpha((int) (255.0f * alpha)); 426 | }else{ 427 | paint.setAlpha(255); 428 | } 429 | this.mMergedLayerCanvas.save(); 430 | this.mMergedLayerCanvas.clipRect(rectF); 431 | this.mMergedLayerCanvas.drawBitmap(this.mDrawingLayer, 0.0f, 0.0f, paint); 432 | this.mMergedLayerCanvas.restore(); 433 | clearDrawingLayer(rectF); 434 | if (!(this.mIsBatchDraw)) { 435 | Rect rect = new Rect(); 436 | rectF.round(rect); 437 | invalidate(rect); 438 | } 439 | 440 | } 441 | 442 | private void clearDrawingLayer(RectF rectF) { 443 | this.mDrawingLayerCanvas.save(); 444 | this.mDrawingLayerCanvas.clipRect(rectF); 445 | this.mDrawingLayerCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC); 446 | this.mDrawingLayerCanvas.restore(); 447 | this.mDrawingLayerNeedDrawn = false; 448 | } 449 | 450 | private void openLine() { 451 | this.mDirtyRect.set(this.mOldPt.x - this.mPathWidthHalf, 452 | this.mOldPt.y - this.mPathWidthHalf, this.mOldPt.x + this.mPathWidthHalf, 453 | this.mOldPt.y + this.mPathWidthHalf); 454 | } 455 | 456 | private void closeLine() { 457 | this.mLineDirtyRect.union(this.mDirtyRect); 458 | if (!(this.mIsBatchDraw)) { 459 | Rect rect = new Rect(); 460 | mDirtyRect.round(rect); 461 | invalidate(rect); 462 | } 463 | } 464 | 465 | private void resetDrawingDirtyRect() { 466 | this.mLineDirtyRect.setEmpty(); 467 | this.mDrawingLayerNeedDrawn = true; 468 | } 469 | 470 | private void drawBrushWithScale(float x, float y, float tipScale) { 471 | 472 | this.mNormalPaint.setAlpha(255); 473 | 474 | if (tipScale == 1.0f) { 475 | mDrawingLayerCanvas.drawBitmap(mPathLayer, x - mPathWidthHalf, y - mPathWidthHalf, mNormalPaint); 476 | }else{ 477 | mDrawingLayerCanvas.save(); 478 | mDrawingLayerCanvas.translate(x, y); 479 | mDrawingLayerCanvas.scale(tipScale, tipScale); 480 | mDrawingLayerCanvas.drawBitmap(mPathLayer, -mPathWidthHalf, -mPathWidthHalf, mNormalPaint); 481 | mDrawingLayerCanvas.restore(); 482 | } 483 | 484 | 485 | } 486 | 487 | private float getBrushSpotAngle(Brush brush, float oldX, float oldY, float curX, float curY) { 488 | float angle = brush.angle * 6.2831855f; 489 | if (brush.useDeviceAngle) { 490 | angle += this.mDeviceAngle; 491 | } 492 | if (brush.useFlowingAngle) { 493 | angle += ((float) Math.atan2((double) (curY - oldY), (double) (curX - oldX))) - 1.5707964f; 494 | } 495 | return brush.angleJitter > 0.0f ? angle + ((this.mRandom.nextFloat() - 0.5f) * 6.2831855f) * brush.angleJitter : angle; 496 | } 497 | 498 | private int jitterColor(int color) { 499 | if (!mIsJitterColor) { 500 | return color; 501 | } 502 | float[] hsv = new float[3]; 503 | Color.colorToHSV(color, hsv); 504 | float hue = hsv[0]; 505 | float saturation = hsv[1]; 506 | hsv[0] = ((hue + (((mRandom.nextFloat() - 0.5f) * 360.0f) * mBrush.jitterHue)) + 360.0f) % 360.0f; 507 | hsv[1] = saturation + (mRandom.nextFloat() - 0.5f) * mBrush.jitterSaturation; 508 | hsv[2] = hsv[2] + (mRandom.nextFloat() - 0.5f) * mBrush.jitterBrightness; 509 | return Color.HSVToColor(hsv); 510 | } 511 | 512 | private void textureBrush(Brush brush, float x, float y) { 513 | this.mDstOutPaint.setAlpha((int) (brush.textureDepth * 255.0f)); 514 | this.mPathLayerCanvas.drawBitmap(this.mTextureLayer, -x, -y, this.mDstOutPaint); 515 | } 516 | 517 | private void smudgingBrush(Brush brush, float x, float y, float tipAlpha) { 518 | x = -x; 519 | y = -y; 520 | this.mTempPathLayerCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC); 521 | this.mTempPathLayerCanvas.drawBitmap(this.mMergedLayer, x, y, null); 522 | this.mNormalPaint.setAlpha((int) (this.mDrawingAlpha * 255.0f)); 523 | this.mTempPathLayerCanvas.drawBitmap(this.mDrawingLayer, x, y, this.mNormalPaint); 524 | this.mNormalPaint.setAlpha((int) ((brush.smudgingPatchAlpha * tipAlpha) * 255.0f)); 525 | this.mPathLayerCanvas.drawBitmap(this.mTempPathLayer, 0.0f, 0.0f, this.mNormalPaint); 526 | } 527 | 528 | @Override 529 | protected void onDetachedFromWindow() { 530 | super.onDetachedFromWindow(); 531 | release(); 532 | } 533 | 534 | public void release() { 535 | releaseViewSizeBitmaps(); 536 | releaseBrushSizeBitmaps(); 537 | } 538 | 539 | private void releaseBrushSizeBitmaps() { 540 | this.mPathLayerCanvas.setBitmap(EMPTY_BITMAP); 541 | if (this.mPathLayer != null) { 542 | this.mPathLayer.recycle(); 543 | this.mPathLayer = null; 544 | } 545 | this.mTempPathLayerCanvas.setBitmap(EMPTY_BITMAP); 546 | if (this.mTempPathLayer != null) { 547 | this.mTempPathLayer.recycle(); 548 | this.mTempPathLayer = null; 549 | } 550 | if (this.mMaskBitmap != null) { 551 | int i = 0; 552 | while (i < this.mMaskBitmap.length) { 553 | if (this.mMaskBitmap[i] != null) { 554 | this.mMaskBitmap[i].recycle(); 555 | this.mMaskBitmap[i] = null; 556 | } 557 | i++; 558 | } 559 | this.mMaskBitmap = null; 560 | } 561 | } 562 | 563 | private void releaseViewSizeBitmaps() { 564 | this.mMergedLayerCanvas.setBitmap(EMPTY_BITMAP); 565 | if (this.mMergedLayer != null) { 566 | this.mMergedLayer.recycle(); 567 | this.mMergedLayer = null; 568 | } 569 | this.mDrawingLayerCanvas.setBitmap(EMPTY_BITMAP); 570 | if (this.mDrawingLayer != null) { 571 | this.mDrawingLayer.recycle(); 572 | this.mDrawingLayer = null; 573 | } 574 | this.mTextureLayerCanvas.setBitmap(EMPTY_BITMAP); 575 | if (this.mTextureLayer != null) { 576 | this.mTextureLayer.recycle(); 577 | this.mTextureLayer = null; 578 | } 579 | } 580 | 581 | private class MyTouchDistanceResampler extends TouchDistanceResampler { 582 | private float mLastDrawDistance; 583 | private float[] mTempXYV = new float[3]; 584 | 585 | @Override 586 | protected void onTouchDown(float x, float y) { 587 | Log.d("PaintView", "onTouchDown"); 588 | this.mLastDrawDistance = 0.0f; 589 | PaintView.this.moveToThread(x, y); 590 | } 591 | 592 | @Override 593 | protected void onTouchMove(float x, float y, float t) { 594 | Log.d("PaintView", "onTouchMove"); 595 | Brush brush = PaintView.this.mBrush; 596 | 597 | openLine(); 598 | while (getXYVAtDistance(this.mLastDrawDistance, this.mTempXYV)) { 599 | float tipSpeedScale; 600 | float tipSpeedAlpha; 601 | float px = this.mTempXYV[0]; 602 | float py = this.mTempXYV[1]; 603 | float pv = this.mTempXYV[2]; 604 | if (brush.lineEndSpeedLength > 0.0f) { 605 | float velocityLevel; 606 | velocityLevel = pv > PaintView.this.mMaxVelocityScale ? 1.0f : pv / PaintView.this.mMaxVelocityScale; 607 | tipSpeedScale = brush.lineEndSizeScale + (1.0f - velocityLevel) * (1.0f - brush.lineEndSizeScale); 608 | tipSpeedAlpha = brush.lineEndAlphaScale + (1.0f - velocityLevel) * (1.0f - brush.lineEndAlphaScale); 609 | } else { 610 | tipSpeedScale = 1.0f; 611 | tipSpeedAlpha = 1.0f; 612 | } 613 | if (this.mLastDrawDistance > 0.0f) { 614 | 615 | Log.d("PaintView", "onTouchMove "+px+", "+py); 616 | PaintView.this.addSpot(px, py, tipSpeedScale, tipSpeedAlpha); 617 | } 618 | this.mLastDrawDistance += PaintView.this.mSpacing * tipSpeedScale; 619 | } 620 | closeLine(); 621 | } 622 | 623 | @Override 624 | protected void onTouchUp() { 625 | Log.d("PaintView", "onTouchUp"); 626 | PaintView.this.destLineThread(); 627 | } 628 | } 629 | 630 | 631 | } 632 | -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/drawing/TouchDistanceResampler.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.drawing; 2 | 3 | /** 4 | * Created by marco.granatiero on 08/08/2014. 5 | */ 6 | 7 | import android.graphics.Path; 8 | import android.graphics.PathMeasure; 9 | import android.graphics.PointF; 10 | import android.util.FloatMath; 11 | 12 | public abstract class TouchDistanceResampler extends TouchResampler { 13 | private float mDistance0; 14 | private float mDistance1; 15 | private float mDistance2; 16 | private float mDistance3; 17 | private float mLastPathTime; 18 | private final Path mPath; 19 | private PointF mPathBezier1; 20 | private final PathMeasure mPathMeasure; 21 | private float[] mTempPos; 22 | private float mTime0; 23 | private float mTime1; 24 | private float mTime2; 25 | private float mTime3; 26 | 27 | public TouchDistanceResampler() { 28 | this.mPathBezier1 = new PointF(); 29 | this.mTempPos = new float[2]; 30 | this.mPath = new Path(); 31 | this.mPathMeasure = new PathMeasure(); 32 | } 33 | 34 | private static float calcInstantVelocity(float da, float db, float dc, float ta, float tb, float tc, float s) { 35 | return ((((da - (2.0f * db)) + dc) * s) - (da - db)) / ((((ta - (2.0f * tb)) + tc) * s) - (ta - tb)); 36 | } 37 | 38 | private static float calcRootOfQuadraticBezier(float a, float b, float c, float distance) { 39 | float A = a - 2.0f * b + c; 40 | float B = a - b; 41 | float C = a - distance; 42 | return A == 0.0f ? (-C) / B : (B + FloatMath.sqrt((B * B) - (A * C))) / A; 43 | } 44 | 45 | protected void addToPath(float x, float y, long t, boolean isMove) { 46 | this.mPath.quadTo(this.mPathBezier1.x, this.mPathBezier1.y, (this.mPathBezier1.x + x) / 2.0f, (this.mPathBezier1.y + y) / 2.0f); 47 | this.mPathBezier1.set(x, y); 48 | this.mPathMeasure.setPath(this.mPath, false); 49 | float totalDistance = this.mPathMeasure.getLength(); 50 | float totalTime = (this.mLastPathTime + ((float) t)) / 2.0f; 51 | if (isMove) { 52 | if (this.mDistance2 == 0.0f) { 53 | this.mDistance0 = 0.0f; 54 | this.mDistance1 = totalDistance / 4.0f; 55 | this.mDistance2 = totalDistance / 2.0f; 56 | this.mTime0 = 0.0f; 57 | this.mTime1 = totalTime / 4.0f; 58 | this.mTime2 = totalTime / 2.0f; 59 | } else { 60 | this.mDistance0 = this.mDistance2; 61 | this.mDistance1 = this.mDistance3; 62 | this.mDistance2 = (this.mDistance1 + totalDistance) / 2.0f; 63 | this.mTime0 = this.mTime2; 64 | this.mTime1 = this.mTime3; 65 | this.mTime2 = (this.mTime1 + totalTime) / 2.0f; 66 | } 67 | this.mDistance3 = totalDistance; 68 | this.mTime3 = totalTime; 69 | super.addToPath(x, y, t, isMove); 70 | } else { 71 | this.mDistance0 = this.mDistance2; 72 | this.mDistance1 = this.mDistance3; 73 | this.mDistance2 = totalDistance; 74 | this.mTime0 = this.mTime2; 75 | this.mTime1 = this.mTime3; 76 | this.mTime2 = this.mLastPathTime; 77 | super.addToPath(x, y, (long) this.mLastPathTime, isMove); 78 | } 79 | this.mLastPathTime = (float) t; 80 | } 81 | 82 | public boolean getXYVAtDistance(float distance, float[] xyv) { 83 | if (this.mDistance2 == 0.0f || distance > this.mDistance2) { 84 | return false; 85 | } 86 | this.mPathMeasure.getPosTan(distance, this.mTempPos, null); 87 | xyv[0] = this.mTempPos[0]; 88 | xyv[1] = this.mTempPos[1]; 89 | xyv[2] = calcInstantVelocity(this.mDistance0, this.mDistance1, this.mDistance2, this.mTime0, this.mTime1, this.mTime2, calcRootOfQuadraticBezier(this.mDistance0, this.mDistance1, this.mDistance2, distance)); 90 | return true; 91 | } 92 | 93 | protected void startPath(float x, float y, long t) { 94 | this.mPath.reset(); 95 | this.mPath.moveTo(x, y); 96 | this.mPathBezier1.set(x, y); 97 | this.mDistance0 = 0.0f; 98 | this.mDistance1 = 0.0f; 99 | this.mDistance2 = 0.0f; 100 | this.mDistance3 = 0.0f; 101 | this.mTime0 = 0.0f; 102 | this.mTime1 = 0.0f; 103 | this.mTime2 = 0.0f; 104 | this.mTime3 = 0.0f; 105 | this.mLastPathTime = 0.0f; 106 | super.startPath(x, y, t); 107 | } 108 | } -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/drawing/TouchResampler.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.drawing; 2 | 3 | /** 4 | * Created by marco.granatiero on 08/08/2014. 5 | */ 6 | 7 | 8 | import android.os.Build.VERSION; 9 | import android.util.Log; 10 | import android.view.MotionEvent; 11 | 12 | public abstract class TouchResampler { 13 | 14 | private static final String TAG = "LineBrush"; 15 | 16 | protected void addToPath(float x, float y, long t, boolean isMove) { 17 | onTouchMove(x, y, (float) t); 18 | } 19 | 20 | protected void endPath() { 21 | onTouchUp(); 22 | } 23 | 24 | public void feedXYT(float[] xyt) { 25 | startPath(xyt[0], xyt[1], (long) xyt[2]); 26 | int i = 3; 27 | while (i < xyt.length) { 28 | addToPath(xyt[i], xyt[i + 1], (long) xyt[i + 2], true); 29 | i += 3; 30 | } 31 | i -= 3; 32 | addToPath(xyt[i], xyt[i + 1], (long) xyt[i + 2], false); 33 | endPath(); 34 | } 35 | 36 | public boolean getXYVAtDistance(float distance, float[] xyv) { 37 | return false; 38 | } 39 | 40 | protected abstract void onTouchDown(float f, float f2); 41 | 42 | public void onTouchEvent(MotionEvent event) { 43 | float x = event.getX(); 44 | float y = event.getY(); 45 | long t = event.getEventTime() - event.getDownTime(); 46 | switch ((VERSION.SDK_INT >= 8 ? event.getActionMasked() : event.getAction() & 255)) { 47 | case MotionEvent.ACTION_DOWN: 48 | Log.d("TouchResampler", "ACTION_DOWN"); 49 | startPath(x, y, t); 50 | break; 51 | case MotionEvent.ACTION_UP: 52 | Log.d("TouchResampler", "ACTION_UP"); 53 | addToPath(x, y, t, false); 54 | endPath(); 55 | break; 56 | case MotionEvent.ACTION_MOVE: 57 | Log.d("TouchResampler", "ACTION_MOVE"); 58 | int i = 0; 59 | while (i < event.getHistorySize()) { 60 | addToPath(event.getHistoricalX(i), event.getHistoricalY(i), event.getHistoricalEventTime(i) - event.getDownTime(), true); 61 | i++; 62 | } 63 | addToPath(x, y, t, true); 64 | break; 65 | default: 66 | break; 67 | } 68 | } 69 | 70 | protected abstract void onTouchMove(float f, float f2, float f3); 71 | 72 | protected abstract void onTouchUp(); 73 | 74 | protected void startPath(float x, float y, long t) { 75 | onTouchDown(x, y); 76 | } 77 | } -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/fragments/BrushSelectFragment.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.fragments; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.AdapterView; 11 | import android.widget.ArrayAdapter; 12 | import android.widget.GridView; 13 | import android.widget.TextView; 14 | 15 | import java.util.List; 16 | 17 | import it.moondroid.paintbrush.PaintBrushApp; 18 | import it.moondroid.paintbrush.R; 19 | import it.moondroid.paintbrush.drawing.Brush; 20 | import it.moondroid.paintbrush.drawing.Brushes; 21 | 22 | /** 23 | * Created by marco.granatiero on 19/08/2014. 24 | */ 25 | 26 | public class BrushSelectFragment extends Fragment implements AdapterView.OnItemClickListener { 27 | 28 | public static BrushSelectFragment newInstance(int brushId, int brushType){ 29 | BrushSelectFragment f = new BrushSelectFragment(); 30 | Bundle args = new Bundle(); 31 | args.putInt(PaintBrushApp.EXTRA_BRUSH_ID, brushId); 32 | args.putInt(PaintBrushApp.EXTRA_BRUSH_TYPE, brushType); 33 | f.setArguments(args); 34 | return f; 35 | } 36 | 37 | private static class BrushAdapter extends ArrayAdapter { 38 | private final LayoutInflater mInflater; 39 | 40 | public BrushAdapter(Context context, List brushes) { 41 | super(context, 0, 0, brushes); 42 | this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 43 | } 44 | 45 | public long getItemId(int position) { 46 | return (long) ((Brush) getItem(position)).id; 47 | } 48 | 49 | public View getView(int position, View convertView, ViewGroup parent) { 50 | if (convertView == null) { 51 | convertView = this.mInflater.inflate(R.layout.brush_gridview_item, parent, false); 52 | } 53 | TextView tv = (TextView) convertView; 54 | Brush brush = (Brush) getItem(position); 55 | tv.setText(brush.name); 56 | tv.setCompoundDrawablesWithIntrinsicBounds(0, brush.previewId, 0, 0); 57 | tv.setEnabled(isEnabled(position)); 58 | return tv; 59 | } 60 | } 61 | 62 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 63 | View v = inflater.inflate(R.layout.fragment_brush_select, null); 64 | GridView brushGridView = (GridView) v.findViewById(R.id.brushGridView); 65 | brushGridView.setOnItemClickListener(this); 66 | int brushType = getArguments().getInt(PaintBrushApp.EXTRA_BRUSH_TYPE, 0); 67 | int brushId = getArguments().getInt(PaintBrushApp.EXTRA_BRUSH_ID, -1); 68 | 69 | List brushes = Brushes.get(getActivity(), brushType); 70 | brushGridView.setAdapter(new BrushAdapter(getActivity(), brushes)); 71 | if (savedInstanceState == null) { 72 | int i = 0; 73 | while (i < brushes.size()) { 74 | if (((Brush) brushes.get(i)).id == brushId) { 75 | brushGridView.setSelection(i); 76 | } 77 | i++; 78 | } 79 | } 80 | return v; 81 | } 82 | 83 | public void onItemClick(AdapterView parent, View view, int position, long id) { 84 | getActivity().setResult(-1, new Intent().putExtra(PaintBrushApp.EXTRA_BRUSH_ID, (int) id)); 85 | getActivity().finish(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/util/ImageUtils.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.util; 2 | 3 | import android.app.Dialog; 4 | import android.app.ProgressDialog; 5 | import android.content.ContentResolver; 6 | import android.content.ContentValues; 7 | import android.content.Context; 8 | import android.database.Cursor; 9 | import android.graphics.Bitmap; 10 | import android.net.Uri; 11 | import android.os.AsyncTask; 12 | import android.os.Environment; 13 | import android.os.SystemClock; 14 | import android.provider.MediaStore; 15 | import android.util.Log; 16 | 17 | import java.io.File; 18 | import java.util.Random; 19 | 20 | import it.moondroid.paintbrush.R; 21 | 22 | import static android.provider.MediaStore.Images.Media; 23 | import static android.provider.MediaStore.Images.Thumbnails; 24 | 25 | /** 26 | * Created by marco.granatiero on 01/09/2014. 27 | */ 28 | public class ImageUtils { 29 | 30 | private static final String TAG = "PaintBrush"; 31 | private static final String DIRECTORY_NAME = "PaintBrush"; 32 | 33 | public static final int ERROR_BITMAP_UNAVAILABLE = 1; 34 | public static final int ERROR_MEDIA_UNMOUNTED = 2; 35 | public static final int ERROR_MKDIR_FAIL = 3; 36 | public static final int ERROR_FILE_NOT_FOUND = 4; 37 | public static final int ERROR_IO_EXCEPTION = 5; 38 | public static final int ERROR_OUT_OF_MEMORY_DECODE_BITMAP = 6; 39 | 40 | private static final String[] PROJECTION_ID_DATA; 41 | private static final Uri IMAGE_URI; 42 | private static final Uri THUMBNAIL_URI; 43 | private static final String PREFIX_PICTURE_FILENAME = "p"; 44 | private static final String THUMBNAIL_DESCRIPTION = "it.moondroid.paintbrush"; 45 | 46 | private static final boolean USE_THUMBNAILS_MEDIA_STORE = true; 47 | 48 | static { 49 | IMAGE_URI = Media.EXTERNAL_CONTENT_URI; 50 | THUMBNAIL_URI = Thumbnails.EXTERNAL_CONTENT_URI; 51 | String[] strArr = new String[2]; 52 | strArr[0] = Media._ID; //"_id"; 53 | strArr[1] = Media.DATA; //"_data"; 54 | PROJECTION_ID_DATA = strArr; 55 | } 56 | 57 | public static interface SaveImageListener { 58 | void onCompleted(Uri uri); 59 | void onError(int i); 60 | } 61 | 62 | private static class ImageSaveProviderAsyncTask extends AsyncTask { 63 | private Bitmap mBitmap; 64 | private final Context mContext; 65 | private int mErrorCode; 66 | private final SaveImageListener mListener; 67 | private Dialog mProgressDialog; 68 | 69 | private ImageSaveProviderAsyncTask(Context context, Bitmap bitmap, SaveImageListener listener) { 70 | this.mErrorCode = 0; 71 | this.mContext = context; 72 | this.mBitmap = bitmap; 73 | this.mListener = listener; 74 | } 75 | 76 | private void setErrorCode(int errorCode) { 77 | this.mErrorCode = errorCode; 78 | } 79 | 80 | @Override 81 | protected void onPreExecute() { 82 | this.mProgressDialog = createProgressDialog(this.mContext, R.string.popup_saving); 83 | this.mProgressDialog.show(); 84 | } 85 | 86 | @Override 87 | protected Uri doInBackground(Void ... params) { 88 | if (this.mBitmap == null) { 89 | setErrorCode(ERROR_BITMAP_UNAVAILABLE); 90 | return null; 91 | } else if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { 92 | long t1 = SystemClock.elapsedRealtime(); 93 | String commonFileName = ImageUtils.generateMagicNumber(); 94 | 95 | Uri uri = null; 96 | if (USE_THUMBNAILS_MEDIA_STORE) { 97 | uri = ImageUtils.insertImageSimple(this.mContext.getContentResolver(), 98 | mBitmap, new File(ImageUtils.getPictureDir(), 99 | PREFIX_PICTURE_FILENAME + commonFileName + ".jpg").getAbsolutePath(), 100 | commonFileName, THUMBNAIL_DESCRIPTION, "image/jpeg"); 101 | } 102 | 103 | return uri; 104 | } else { 105 | setErrorCode(ERROR_MEDIA_UNMOUNTED); 106 | return null; 107 | } 108 | } 109 | 110 | @Override 111 | protected void onPostExecute(Uri result) { 112 | this.mProgressDialog.dismiss(); 113 | if (result == null) { 114 | this.mListener.onError(this.mErrorCode); 115 | return; 116 | } 117 | this.mListener.onCompleted(result); 118 | } 119 | 120 | } 121 | 122 | private static String generateMagicNumber() { 123 | StringBuilder stringBuilder = new StringBuilder().append(Long.toString(System.currentTimeMillis())); 124 | Object[] objArr = new Object[1]; 125 | objArr[0] = Integer.valueOf(new Random().nextInt(100)); 126 | return stringBuilder.append(String.format("%02d", objArr)).toString(); 127 | } 128 | 129 | private static final File getPictureDir() { 130 | if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { 131 | return null; 132 | } 133 | File dir = new File(Environment.getExternalStorageDirectory(), DIRECTORY_NAME); 134 | return (dir.exists() || dir.mkdir()) ? dir : null; 135 | } 136 | 137 | private static final Uri insertImageSimple(ContentResolver cr, Bitmap source, String path, String title, String description, String mimeType) { 138 | if (source == null) { 139 | Log.e(TAG, "source bitmap is null"); 140 | return null; 141 | } 142 | String stringUrl = Media.insertImage(cr, source, title, description); 143 | if (stringUrl == null) { 144 | Log.e(TAG, "stringUrl is null"); 145 | return null; 146 | } 147 | Uri uri = Uri.parse(stringUrl); 148 | Cursor c = cr.query(uri, PROJECTION_ID_DATA, null, null, null); 149 | long fileSize = 0; 150 | if (c != null) { 151 | if ((!c.moveToFirst()) || c.getString(c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)) == null) { 152 | c.close(); 153 | } else { 154 | File src = new File(c.getString(c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))); 155 | fileSize = src.length(); 156 | if (!src.renameTo(new File(path))) { 157 | Log.e(TAG, "insertImageSimple rename fail"); 158 | } 159 | c.close(); 160 | } 161 | } 162 | 163 | //Create any metadata for image 164 | ContentValues values = new ContentValues(); 165 | if (mimeType != null) { 166 | values.put(MediaStore.Images.Media.MIME_TYPE, mimeType); 167 | } 168 | values.put(MediaStore.Images.Media.DATA, path); 169 | if (fileSize > 0) { 170 | values.put(MediaStore.Images.Media.SIZE, Long.valueOf(fileSize)); 171 | } 172 | 173 | final long nowMillis = System.currentTimeMillis(); 174 | values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, nowMillis); 175 | values.put(MediaStore.Images.ImageColumns.DATE_ADDED, nowMillis / 1000); 176 | values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, nowMillis / 1000); 177 | 178 | int result = cr.update(uri, values, null, null); 179 | return uri; 180 | } 181 | 182 | public static Dialog createProgressDialog(Context context, int messageId) { 183 | ProgressDialog dialog = new ProgressDialog(context); 184 | dialog.setMessage(context.getResources().getString(messageId)); 185 | dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 186 | dialog.setIndeterminate(true); 187 | dialog.setCancelable(false); 188 | 189 | return dialog; 190 | } 191 | 192 | public static void saveImageFromBitmap(Context context, Bitmap bitmap, SaveImageListener listener) { 193 | new ImageSaveProviderAsyncTask(context, bitmap, listener).execute(new Void[0]); 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/widget/OpacityPopupWindow.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.widget; 2 | 3 | /** 4 | * Created by marco.granatiero on 08/08/2014. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.widget.TextView; 12 | 13 | import it.moondroid.paintbrush.R; 14 | 15 | public class OpacityPopupWindow extends ValuePopupWindow { 16 | private TextView mTextView; 17 | 18 | public OpacityPopupWindow(Context context) { 19 | super(context); 20 | View v = LayoutInflater.from(context).inflate(R.layout.opacity_popup, null); 21 | this.mTextView = (TextView) v.findViewById(R.id.opacityPopupText); 22 | setContentView(v); 23 | } 24 | 25 | protected void setConvertedValue(float value) { 26 | this.mTextView.setText(Integer.toString((int) (value))); 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/widget/PopupSeekBar.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.widget; 2 | 3 | /** 4 | * Created by marco.granatiero on 08/08/2014. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.util.AttributeSet; 9 | import android.view.Gravity; 10 | import android.widget.SeekBar; 11 | 12 | 13 | public class PopupSeekBar extends SeekBar { 14 | 15 | private OnSeekBarChangeListener mOnSeekBarChangeListener; 16 | private OnSeekBarChangeListener mOnSeekBarChangeListenerForPopup; 17 | private ValuePopupWindow mPopup; 18 | 19 | public PopupSeekBar(Context context, AttributeSet attrs) { 20 | 21 | super(context, attrs); 22 | 23 | mOnSeekBarChangeListenerForPopup = new OnSeekBarChangeListener() { 24 | 25 | @Override 26 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 27 | if (mOnSeekBarChangeListener != null) { 28 | mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser); 29 | } 30 | if (fromUser && mPopup != null) { 31 | mPopup.setValue(progress); 32 | } 33 | } 34 | 35 | @Override 36 | public void onStartTrackingTouch(SeekBar seekBar) { 37 | if (mOnSeekBarChangeListener != null) { 38 | mOnSeekBarChangeListener.onStartTrackingTouch(seekBar); 39 | } 40 | if (mPopup != null) { 41 | mPopup.setValue(seekBar.getProgress()); 42 | mPopup.showAtLocation(PopupSeekBar.this, Gravity.CENTER, 0, 0); 43 | } 44 | } 45 | 46 | @Override 47 | public void onStopTrackingTouch(SeekBar seekBar) { 48 | if (mOnSeekBarChangeListener != null) { 49 | mOnSeekBarChangeListener.onStopTrackingTouch(seekBar); 50 | } 51 | if (mPopup != null) { 52 | mPopup.dismiss(); 53 | } 54 | } 55 | }; 56 | setOnSeekBarChangeListener(null); 57 | } 58 | 59 | @Override 60 | public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) { 61 | super.setOnSeekBarChangeListener(mOnSeekBarChangeListenerForPopup); 62 | mOnSeekBarChangeListener = l; 63 | } 64 | 65 | public void setValuePopupWindow(ValuePopupWindow popup) { 66 | mPopup = popup; 67 | } 68 | } -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/widget/SizePopupWindow.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.widget; 2 | 3 | /** 4 | * Created by marco.granatiero on 08/08/2014. 5 | */ 6 | 7 | 8 | import android.content.Context; 9 | import android.graphics.Canvas; 10 | import android.graphics.Paint; 11 | import android.util.AttributeSet; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.widget.TextView; 15 | 16 | import it.moondroid.paintbrush.R; 17 | 18 | 19 | public class SizePopupWindow extends ValuePopupWindow { 20 | private CircleView mCircleView; 21 | private TextView mTextView; 22 | 23 | public static class CircleView extends View { 24 | private Paint mPaint; 25 | private float mRadius; 26 | 27 | public CircleView(Context context, AttributeSet attrs) { 28 | super(context, attrs); 29 | this.mPaint = new Paint(1); 30 | } 31 | 32 | private void setCircleColor(int color) { 33 | this.mPaint.setColor(color); 34 | invalidate(); 35 | } 36 | 37 | private void setCircleRadius(float radius) { 38 | this.mRadius = radius; 39 | invalidate(); 40 | } 41 | 42 | protected void onDraw(Canvas canvas) { 43 | super.onDraw(canvas); 44 | canvas.drawCircle((float) (canvas.getWidth() / 2), (float) (canvas.getHeight() / 2), this.mRadius, this.mPaint); 45 | } 46 | } 47 | 48 | public SizePopupWindow(Context context) { 49 | super(context); 50 | View v = LayoutInflater.from(context).inflate(R.layout.size_popup, null); 51 | this.mTextView = (TextView) v.findViewById(R.id.sizePopupText); 52 | this.mCircleView = (CircleView) v.findViewById(R.id.sizePopupCircle); 53 | this.mCircleView.setCircleColor(-1); 54 | setContentView(v); 55 | } 56 | 57 | protected void setConvertedValue(float value) { 58 | if (this.mTextView.getTextSize() > 0.5f * value) { 59 | this.mTextView.setVisibility(View.GONE); 60 | } else { 61 | this.mTextView.setVisibility(View.VISIBLE); 62 | this.mTextView.setText(Integer.toString((int) value)); 63 | } 64 | this.mCircleView.setCircleRadius(value / 2.0f); 65 | } 66 | } -------------------------------------------------------------------------------- /app/src/main/java/it/moondroid/paintbrush/widget/ValuePopupWindow.java: -------------------------------------------------------------------------------- 1 | package it.moondroid.paintbrush.widget; 2 | 3 | /** 4 | * Created by marco.granatiero on 08/08/2014. 5 | */ 6 | 7 | 8 | import android.content.Context; 9 | import android.widget.PopupWindow; 10 | 11 | import it.moondroid.paintbrush.R; 12 | 13 | 14 | public abstract class ValuePopupWindow extends PopupWindow { 15 | 16 | public ValuePopupWindow(Context context) { 17 | super(context); 18 | prepare(context); 19 | } 20 | 21 | protected float convertValue(float value) { 22 | return value; 23 | } 24 | 25 | protected void prepare(Context context) { 26 | int width = context.getResources().getDimensionPixelSize(R.dimen.popup_width); 27 | int height = context.getResources().getDimensionPixelSize(R.dimen.popup_height); 28 | setWidth(width); 29 | setHeight(height); 30 | setBackgroundDrawable(context.getResources().getDrawable(R.drawable.brush_opacity_size_bg)); 31 | } 32 | 33 | protected abstract void setConvertedValue(float f); 34 | 35 | public final void setValue(float value) { 36 | setConvertedValue(convertValue(value)); 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_01.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_01_gb45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_01_gb45.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_03.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_03_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_03_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_04.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_05.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_07.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_10.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_10_gb11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_10_gb11.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_10_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_10_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_12.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_12_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_12_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_14.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_14_gb50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_14_gb50.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_18.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_18_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_18_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_19.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_19_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_19_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_22.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_22_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_22_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_28.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_32.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_32_gb12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_32_gb12.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_33.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_41.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_41_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_41_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_42.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_42_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_42_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_43.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_43_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_43_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_44.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_44_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_44_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_45.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_45_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_45_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_46.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_46_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_46_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_47.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_47_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_47_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_48.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_48_gb15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_48_gb15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_49.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_49_gb12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_49_gb12.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_53.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_54.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_54.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_55.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_56.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_60.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/brush_60_gb50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/brush_60_gb50.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_01.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_02.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_03.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_04.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_05.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_06.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_07.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_08.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_09.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_10.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_11.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_12.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_13.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_14.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_15.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_16.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_17.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_18.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_19.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_20.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_21.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_22.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_23.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_24.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_25.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_26.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_27.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_28.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_29.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_30.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_31.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_32.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_33.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_34.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_35.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_36.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_37.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_38.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_39.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_40.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_41.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/main_brush_icon_42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/main_brush_icon_42.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_acrylic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_acrylic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_air_brush.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_air_brush.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_fish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_fish.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_flowers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_flowers.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_hard_pastel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_hard_pastel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_impress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_impress.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_oil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_oil.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_oil_pastel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_oil_pastel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_pen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_pen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_renoir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_renoir.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_seurat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_seurat.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_van_gogh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_van_gogh.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_water_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_water_color.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_wet_canvas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_wet_canvas.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/photobrush_wet_sponge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/photobrush_wet_sponge.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_air_brush.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_air_brush.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_ballpoint_pen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_ballpoint_pen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_bamboo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_bamboo1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_bamboo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_bamboo2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_calligraphy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_calligraphy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_colorless_oil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_colorless_oil.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_coub_knife.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_coub_knife.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_creyon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_creyon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_felt_pen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_felt_pen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_finger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_finger.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_fish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_fish.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_flowers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_flowers.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_hard_pastel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_hard_pastel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_hard_pencil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_hard_pencil.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_head_eraser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_head_eraser.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_ink_pen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_ink_pen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_ink_spot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_ink_spot.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_knife1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_knife1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_knife2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_knife2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_oil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_oil.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_oil_pastel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_oil_pastel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_pastel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_pastel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_pen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_pen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_soft_eraser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_soft_eraser.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_soft_pencil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_soft_pencil.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_sponge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_sponge.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/stylishbrush_water_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/stylishbrush_water_color.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/texture01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-nodpi/texture01.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/brush_opacity_top_line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-xhdpi/brush_opacity_top_line.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/brush_scroll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-xhdpi/brush_scroll.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_visibility_toggle_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/brush_opacity_bottom_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/brush_opacity_bottom_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/brush_opacity_center_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/brush_opacity_center_mask.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/brush_opacity_size_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/brush_opacity_size_bg.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/brush_select.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/brush_select.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/brush_selector_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/brush_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/brush_size.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/color_palette_bottom_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/color_palette_bottom_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/color_palette_center_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/color_palette_center_mask.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/color_palette_top_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/color_palette_top_btn.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/opacity_layer.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/palette_brightness.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/palette_brightness.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/palette_pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/palette_pattern.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/palette_pattern_tile.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/palette_shadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/palette_shadow.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/photo_view_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/photo_view_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/photo_view_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/app/src/main/res/drawable/photo_view_on.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/size_layer.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_brush_select.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 21 | 22 | 23 | 28 | 29 | 33 | 34 | 39 | 40 | 41 | 47 | 48 | 51 | 52 | 56 | 57 | 61 | 62 | 65 | 66 | 67 | 77 | 78 | 79 | 80 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /app/src/main/res/layout/brush_gridview_item.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_brush_select.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/opacity_popup.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 18 | 19 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/size_popup.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 11 | 15 | 16 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/brush_attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /app/src/main/res/values/brush_strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Bamboo1Old 4 | Bamboo1 5 | Bamboo2 6 | Pen 7 | HardPencil 8 | SoftPencil 9 | InkPen 10 | HardEraser 11 | SoftEraser 12 | BallpointPen 13 | AirBrush 14 | Oil 15 | FeltPen 16 | WaterColor 17 | OilPastel 18 | Pastel 19 | HardPastel 20 | Creyon 21 | Calligraphy 22 | Knife1 23 | Knife2 24 | CombKnife 25 | ColorlessOil 26 | Finger 27 | InkSpot 28 | Flowers 29 | Fish 30 | Sponge 31 | VanGogh 32 | Renoir 33 | Seurat 34 | WetCanvas 35 | WetSponge 36 | Impress 37 | Oil 38 | WaterColor 39 | Acrylic 40 | Pen 41 | Fish 42 | Flowers 43 | HardPastel 44 | AirBrush 45 | OilPastel 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 94.0dip 7 | 2.0dip 8 | 6.669983dip 9 | 6.669983dip 10 | 55.0dip 11 | 10.0sp 12 | 72.0dip 13 | 84.0dip 14 | 37.33499dip 15 | 43.664978dip 16 | -14.0dip 17 | 13.329987dip 18 | 73dip 19 | 20 | 161.32999dip 21 | 161.32999dip 22 | 23 | 150.0dip 24 | 14.0sp 25 | 4.0dip 26 | 4.669983dip 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PaintBrush 5 | Hello world! 6 | Settings 7 | Delete 8 | Save 9 | 10 | Size 11 | Opacity 12 | Pick a color 13 | Pick a brush 14 | 15 | Are you sure you want to delete this painting? 16 | Delete 17 | Cancel 18 | 19 | Loading… 20 | Saving… 21 | 22 | image saved 23 | save error 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 14 | 21 | 29 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.1.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moondroid/PaintBrush/bc96454122fd4f8345944d135a1a72ab49e4c49a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Mar 30 12:52:52 CEST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------