Browse Source

Implement zoom start position. Closes #92. Rapid decoder properly throws an error when it fails to decode.

inorichi 9 years ago
parent
commit
391550f49a

+ 4 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java

@@ -116,6 +116,10 @@ public class PreferencesHelper {
         return rxPrefs.getInteger(getKey(R.string.pref_image_decoder_key), 0);
     }
 
+    public Preference<Integer> zoomStart() {
+        return rxPrefs.getInteger(getKey(R.string.pref_zoom_start_key), 1);
+    }
+
     public Preference<Integer> readerTheme() {
         return rxPrefs.getInteger(getKey(R.string.pref_reader_theme_key), 0);
     }

+ 17 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java

@@ -43,9 +43,10 @@ public class ReaderMenu {
     @Bind(R.id.page_seeker) SeekBar seekBar;
     @Bind(R.id.total_pages) TextView totalPages;
     @Bind(R.id.lock_orientation) ImageButton lockOrientation;
+    @Bind(R.id.reader_zoom_selector) ImageButton zoomSelector;
+    @Bind(R.id.reader_scale_type_selector) ImageButton scaleTypeSelector;
     @Bind(R.id.reader_selector) ImageButton readerSelector;
     @Bind(R.id.reader_extra_settings) ImageButton extraSettings;
-    @Bind(R.id.reader_scale_type_selector) ImageButton scaleTypeSelector;
 
     private MenuItem nextChapterBtn;
     private MenuItem prevChapterBtn;
@@ -189,9 +190,23 @@ public class ReaderMenu {
         lockOrientation.setOnClickListener(v ->
                 preferences.lockOrientation().set(!preferences.lockOrientation().get()));
 
+        // Zoom selector
+        zoomSelector.setOnClickListener(v -> {
+            showImmersiveDialog(new MaterialDialog.Builder(activity)
+                    .title(R.string.pref_zoom_start)
+                    .items(R.array.zoom_start)
+                    .itemsCallbackSingleChoice(preferences.zoomStart().get() - 1,
+                            (d, itemView, which, text) -> {
+                                preferences.zoomStart().set(which + 1);
+                                return true;
+                            })
+                    .build());
+        });
+
         // Scale type selector
         scaleTypeSelector.setOnClickListener(v -> {
             showImmersiveDialog(new MaterialDialog.Builder(activity)
+                    .title(R.string.pref_image_scale_type)
                     .items(R.array.image_scale_type)
                     .itemsCallbackSingleChoice(preferences.imageScaleType().get() - 1,
                             (d, itemView, which, text) -> {
@@ -205,6 +220,7 @@ public class ReaderMenu {
         readerSelector.setOnClickListener(v -> {
             final Manga manga = activity.getPresenter().getManga();
             showImmersiveDialog(new MaterialDialog.Builder(activity)
+                    .title(R.string.pref_viewer_type)
                     .items(R.array.viewers_selector)
                     .itemsCallbackSingleChoice(manga.viewer,
                             (d, itemView, which, text) -> {

+ 33 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.java

@@ -6,10 +6,13 @@ import android.view.ViewGroup;
 import java.util.List;
 
 import eu.kanade.tachiyomi.R;
+import eu.kanade.tachiyomi.data.preference.PreferencesHelper;
 import eu.kanade.tachiyomi.data.source.model.Page;
 import eu.kanade.tachiyomi.ui.reader.viewer.base.BaseReader;
 import eu.kanade.tachiyomi.ui.reader.viewer.base.OnChapterBoundariesOutListener;
 import eu.kanade.tachiyomi.ui.reader.viewer.base.OnChapterSingleTapListener;
+import eu.kanade.tachiyomi.ui.reader.viewer.pager.horizontal.LeftToRightReader;
+import eu.kanade.tachiyomi.ui.reader.viewer.pager.horizontal.RightToLeftReader;
 import rx.subscriptions.CompositeSubscription;
 
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -24,6 +27,12 @@ public abstract class PagerReader extends BaseReader {
     protected CompositeSubscription subscriptions;
 
     protected int scaleType = 1;
+    protected int zoomStart = 1;
+
+    public static final int ALIGN_AUTO = 1;
+    public static final int ALIGN_LEFT = 2;
+    public static final int ALIGN_RIGHT = 3;
+    public static final int ALIGN_CENTER = 4;
 
     protected void initializePager(Pager pager) {
         this.pager = pager;
@@ -61,22 +70,30 @@ public abstract class PagerReader extends BaseReader {
         adapter = new PagerReaderAdapter(getChildFragmentManager());
         pager.setAdapter(adapter);
 
+        PreferencesHelper preferences = getReaderActivity().getPreferences();
         subscriptions = new CompositeSubscription();
-        subscriptions.add(getReaderActivity().getPreferences().imageDecoder()
+        subscriptions.add(preferences.imageDecoder()
                 .asObservable()
                 .doOnNext(this::setDecoderClass)
                 .skip(1)
                 .distinctUntilChanged()
                 .subscribe(v -> adapter.notifyDataSetChanged()));
 
-        subscriptions.add(getReaderActivity().getPreferences().imageScaleType()
+        subscriptions.add(preferences.imageScaleType()
                 .asObservable()
                 .doOnNext(this::setImageScaleType)
                 .skip(1)
                 .distinctUntilChanged()
                 .subscribe(v -> adapter.notifyDataSetChanged()));
 
-        subscriptions.add(getReaderActivity().getPreferences().enableTransitions()
+        subscriptions.add(preferences.zoomStart()
+                .asObservable()
+                .doOnNext(this::setZoomStart)
+                .skip(1)
+                .distinctUntilChanged()
+                .subscribe(v -> adapter.notifyDataSetChanged()));
+
+        subscriptions.add(preferences.enableTransitions()
                 .asObservable()
                 .subscribe(value -> transitions = value));
 
@@ -125,6 +142,19 @@ public abstract class PagerReader extends BaseReader {
         this.scaleType = scaleType;
     }
 
+    private void setZoomStart(int zoomStart) {
+        if (zoomStart == ALIGN_AUTO) {
+            if (this instanceof LeftToRightReader)
+                setZoomStart(ALIGN_LEFT);
+            else if (this instanceof RightToLeftReader)
+                setZoomStart(ALIGN_RIGHT);
+            else
+                setZoomStart(ALIGN_CENTER);
+        } else {
+            this.zoomStart = zoomStart;
+        }
+    }
+
     public abstract void onFirstPageOut();
     public abstract void onLastPageOut();
 

+ 19 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.java

@@ -1,5 +1,6 @@
 package eu.kanade.tachiyomi.ui.reader.viewer.pager;
 
+import android.graphics.PointF;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.v4.content.ContextCompat;
@@ -70,6 +71,23 @@ public class PagerReaderFragment extends BaseFragment {
         imageView.setVerticalScrollingParent(parentFragment instanceof VerticalReader);
         imageView.setOnTouchListener((v, motionEvent) -> parentFragment.onImageTouch(motionEvent));
         imageView.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() {
+            @Override
+            public void onReady() {
+                switch (parentFragment.zoomStart) {
+                    case PagerReader.ALIGN_LEFT:
+                        imageView.setScaleAndCenter(imageView.getScale(), new PointF(0, 0));
+                        break;
+                    case PagerReader.ALIGN_RIGHT:
+                        imageView.setScaleAndCenter(imageView.getScale(), new PointF(99999f, 0));
+                        break;
+                    case PagerReader.ALIGN_CENTER:
+                        PointF center = imageView.getCenter();
+                        center.y = 0;
+                        imageView.setScaleAndCenter(imageView.getScale(), center);
+                        break;
+                }
+            }
+
             @Override
             public void onImageLoadError(Exception e) {
                 showImageLoadError();
@@ -93,6 +111,7 @@ public class PagerReaderFragment extends BaseFragment {
     public void onDestroyView() {
         unsubscribeProgress();
         unsubscribeStatus();
+        imageView.setOnImageEventListener(null);
         ButterKnife.unbind(this);
         super.onDestroyView();
     }

BIN
app/src/main/res/drawable-hdpi/ic_crop_original_white_24dp.png


BIN
app/src/main/res/drawable-ldpi/ic_crop_original_white_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_crop_original_white_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_crop_original_white_24dp.png


BIN
app/src/main/res/drawable-xxhdpi/ic_crop_original_white_24dp.png


BIN
app/src/main/res/drawable-xxxhdpi/ic_crop_original_white_24dp.png


+ 11 - 0
app/src/main/res/layout/reader_menu.xml

@@ -78,6 +78,16 @@
                 android:src="@drawable/ic_screen_rotation"
                 android:layout_gravity="center_vertical"
                 android:background="?android:selectableItemBackground" />
+
+            <ImageButton
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:id="@+id/reader_zoom_selector"
+                android:src="@drawable/ic_crop_original_white_24dp"
+                android:layout_gravity="center_vertical"
+                android:background="?android:selectableItemBackground"/>
+
             <ImageButton
                 android:layout_width="0dp"
                 android:layout_height="match_parent"
@@ -95,6 +105,7 @@
                 android:src="@drawable/ic_view_carousel"
                 android:layout_gravity="center_vertical"
                 android:background="?android:selectableItemBackground" />
+
             <ImageButton
                 android:layout_width="0dp"
                 android:layout_height="match_parent"

+ 14 - 0
app/src/main/res/values/arrays.xml

@@ -66,6 +66,20 @@
         <item>6</item>
     </string-array>
 
+    <string-array name="zoom_start">
+        <item>@string/zoom_start_automatic</item>
+        <item>@string/zoom_start_left</item>
+        <item>@string/zoom_start_right</item>
+        <item>@string/zoom_start_center</item>
+    </string-array>
+
+    <string-array name="zoom_start_values">
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+    </string-array>
+
     <string-array name="library_update_interval">
         <item>@string/update_never</item>
         <item>@string/update_1hour</item>

+ 1 - 0
app/src/main/res/values/keys.xml

@@ -17,6 +17,7 @@
 
     <string name="pref_default_viewer_key">pref_default_viewer_key</string>
     <string name="pref_image_scale_type_key">pref_image_scale_type_key</string>
+    <string name="pref_zoom_start_key">pref_zoom_start_key</string>
     <string name="pref_hide_status_bar_key">pref_hide_status_bar_key</string>
     <string name="pref_lock_orientation_key">pref_lock_orientation_key</string>
     <string name="pref_enable_transitions_key">pref_enable_transitions_key</string>

+ 6 - 2
app/src/main/res/values/strings.xml

@@ -93,7 +93,7 @@
     <string name="left_to_right_viewer">Left to right</string>
     <string name="right_to_left_viewer">Right to left</string>
     <string name="vertical_viewer">Vertical</string>
-    <string name="webtoon_viewer">Webtoon (experimental)</string>
+    <string name="webtoon_viewer">Webtoon</string>
     <string name="pref_image_decoder">Image decoder</string>
     <string name="rapid_decoder">Rapid</string>
     <string name="skia_decoder">Skia</string>
@@ -104,7 +104,11 @@
     <string name="scale_type_fit_height">Fit height</string>
     <string name="scale_type_original_size">Original size</string>
     <string name="scale_type_smart_fit">Smart fit</string>
-
+    <string name="pref_zoom_start">Zoom start position</string>
+    <string name="zoom_start_automatic">Automatic</string>
+    <string name="zoom_start_left">Left</string>
+    <string name="zoom_start_right">Right</string>
+    <string name="zoom_start_center">Center</string>
 
       <!-- Downloads section -->
     <string name="pref_download_directory">Downloads directory</string>

+ 8 - 0
app/src/main/res/xml/pref_reader.xml

@@ -37,6 +37,14 @@
         android:defaultValue="1"
         android:summary="%s"/>
 
+    <eu.kanade.tachiyomi.widget.preference.IntListPreference
+        android:title="@string/pref_zoom_start"
+        android:key="@string/pref_zoom_start_key"
+        android:entries="@array/zoom_start"
+        android:entryValues="@array/zoom_start_values"
+        android:defaultValue="1"
+        android:summary="%s"/>
+
     <eu.kanade.tachiyomi.widget.preference.IntListPreference
         android:title="@string/pref_reader_theme"
         android:key="@string/pref_reader_theme_key"

+ 7 - 5
libs/SubsamplingScaleImageView/src/com/davemorrissey/labs/subscaleview/decoder/RapidImageRegionDecoder.java

@@ -6,8 +6,6 @@ import android.graphics.Point;
 import android.graphics.Rect;
 import android.net.Uri;
 
-import com.davemorrissey.labs.subscaleview.decoder.ImageRegionDecoder;
-
 import rapid.decoder.BitmapDecoder;
 
 /**
@@ -26,15 +24,19 @@ public class RapidImageRegionDecoder implements ImageRegionDecoder {
     public Point init(Context context, Uri uri) throws Exception {
         decoder = BitmapDecoder.from(context, uri);
         decoder.useBuiltInDecoder(true);
-        return new Point(decoder.sourceWidth(), decoder.sourceHeight());
+        int width = decoder.sourceWidth();
+        int height = decoder.sourceHeight();
+        if (width == 0 || height == 0)
+            throw new Exception("Rapid image decoder returned empty image - image format may not be supported");
+        return new Point(width, height);
     }
 
     @Override
     public synchronized Bitmap decodeRegion(Rect sRect, int sampleSize) {
         try {
-            return decoder.reset().region(sRect).scale(sRect.width()/sampleSize, sRect.height()/sampleSize).decode();
+            return decoder.reset().region(sRect).scale(sRect.width() / sampleSize, sRect.height() / sampleSize).decode();
         } catch (Exception e) {
-            return null;
+            throw new RuntimeException("Rapid image decoder returned null bitmap - image format may not be supported");
         }
     }