Repository: Rogero0o/MissView
Branch: master
Commit: 1486df5e811d
Files: 54
Total size: 177.8 KB
Directory structure:
gitextract_d2mizj6n/
├── .gitignore
├── .idea/
│ ├── .name
│ ├── compiler.xml
│ ├── copyright/
│ │ └── profiles_settings.xml
│ ├── encodings.xml
│ ├── gradle.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── runConfigurations.xml
│ └── vcs.xml
├── MissView.iml
├── README.md
├── build.gradle
├── demo/
│ ├── .gitignore
│ ├── build.gradle
│ ├── demo.iml
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── roger/
│ │ └── missview/
│ │ └── ApplicationTest.java
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── roger/
│ │ └── missview/
│ │ └── MainActivity.java
│ └── res/
│ ├── layout/
│ │ └── activity_main.xml
│ ├── menu/
│ │ └── menu_main.xml
│ ├── values/
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── values-w820dp/
│ └── dimens.xml
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── library/
│ ├── .gitignore
│ ├── build.gradle
│ ├── library.iml
│ ├── libs/
│ │ └── picasso-2.1.1.jar
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── roger/
│ │ └── missview/
│ │ └── library/
│ │ └── ApplicationTest.java
│ └── main/
│ ├── AndroidManifest.xml
│ └── java/
│ └── com/
│ └── roger/
│ └── missview/
│ └── library/
│ ├── BlurRenderer.java
│ ├── DemoRenderController.java
│ ├── GLColorOverlay.java
│ ├── GLPicture.java
│ ├── GLTextureView.java
│ ├── GLUtil.java
│ ├── MissView.java
│ ├── RenderController.java
│ └── util/
│ ├── ArtDetailViewport.java
│ ├── BitmapRegionLoader.java
│ ├── ImageBlurrer.java
│ ├── ImageUtil.java
│ ├── MathUtil.java
│ ├── TickingFloatAnimator.java
│ └── UriUtil.java
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
================================================
FILE: .idea/.name
================================================
MissView
================================================
FILE: .idea/compiler.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>
================================================
FILE: .idea/copyright/profiles_settings.xml
================================================
<component name="CopyrightManager">
<settings default="" />
</component>
================================================
FILE: .idea/encodings.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
================================================
FILE: .idea/gradle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/demo" />
<option value="$PROJECT_DIR$/library" />
</set>
</option>
<option name="myModules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/demo" />
<option value="$PROJECT_DIR$/library" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>
================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
<component name="masterDetails">
<states>
<state key="ProjectJDKs.UI">
<settings>
<last-edited>1.8</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>
================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/MissView.iml" filepath="$PROJECT_DIR$/MissView.iml" />
<module fileurl="file://$PROJECT_DIR$/demo/demo.iml" filepath="$PROJECT_DIR$/demo/demo.iml" />
<module fileurl="file://$PROJECT_DIR$/library/library.iml" filepath="$PROJECT_DIR$/library/library.iml" />
</modules>
</component>
</project>
================================================
FILE: .idea/runConfigurations.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
================================================
FILE: MissView.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="MissView" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
================================================
FILE: README.md
================================================
# MissView
This project is a part of Muzei,(https://github.com/romannurik/muzei) .<br>
Thanks for Roman Nurik..<br>
I like the animation in that project...so i studied his codes and make this..<br>

..as you see right now,wish you like it.
### Step
Import this project into android studio..it's built with it.
### Usage
#### Jcenter
gradle
```
compile 'com.roger.missview.library:library:1.0.0'
```
##### Config in xml
```xml
<com.roger.missview.library.MissView
android:id="@+id/missview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
```
##### and init in java code
```java
mMissview = (MissView) findViewById(R.id.missview);
mMissview.initPicture(path);//path is the String of background picture path
```
## About me
A small guy in mainland FUJIAN China.
If you have any new idea about this project, feel free to tell me ,Tks. :smiley:
## License
The MIT License (MIT)
Copyright © 2015 Roger
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.+'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'
classpath 'com.github.dcendents:android-maven-plugin:1.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
================================================
FILE: demo/.gitignore
================================================
/build
================================================
FILE: demo/build.gradle
================================================
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.roger.missview"
minSdkVersion 19
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
compile project(':library')
}
================================================
FILE: demo/demo.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":demo" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="MissView" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":demo" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/mockable-android-21.jar" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="mockable-android-21" level="project" />
<orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" />
<orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
<orderEntry type="module" module-name="library" exported="" />
</component>
</module>
================================================
FILE: demo/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in F:\adt-bundle-windows-x86_64_with_Android_5.0\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: demo/src/androidTest/java/com/roger/missview/ApplicationTest.java
================================================
package com.roger.missview;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
================================================
FILE: demo/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.roger.missview">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
================================================
FILE: demo/src/main/java/com/roger/missview/MainActivity.java
================================================
package com.roger.missview;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import com.roger.missview.library.MissView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MainActivity extends Activity {
private final String IMAGE_NAME = "night.jpg";
MissView mMissview;
String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initImage();//将图片从assets考到SD卡
mMissview = (MissView) findViewById(R.id.missview);
Bitmap bit = BitmapFactory.decodeResource(this.getResources(),R.drawable.night);
mMissview.initPicture(bit);
}
private void initImage() {
try {
path = getSDPath() + "/" + IMAGE_NAME;
File image = new File(path);
if (image.exists()) {
return;
}
assetsDataToSD(path);
} catch (IOException e) {
e.printStackTrace();
}
}
private void assetsDataToSD(String fileName) throws IOException {
InputStream myInput;
OutputStream myOutput = new FileOutputStream(fileName);
myInput = this.getAssets().open(IMAGE_NAME);
byte[] buffer = new byte[1024];
int length = myInput.read(buffer);
while (length > 0) {
myOutput.write(buffer, 0, length);
length = myInput.read(buffer);
}
myOutput.flush();
myInput.close();
myOutput.close();
}
public String getSDPath() {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState()
.equals(android.os.Environment.MEDIA_MOUNTED); //判断sd卡是否存在
if (sdCardExist) //如果SD卡存在,则获取跟目录
{
sdDir = Environment.getExternalStorageDirectory();//获取跟目录
}
return sdDir.toString();
}
}
================================================
FILE: demo/src/main/res/layout/activity_main.xml
================================================
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.roger.missview.library.MissView
android:id="@+id/missview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
================================================
FILE: demo/src/main/res/menu/menu_main.xml
================================================
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/action_settings" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>
================================================
FILE: demo/src/main/res/values/dimens.xml
================================================
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
================================================
FILE: demo/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">Missview</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
</resources>
================================================
FILE: demo/src/main/res/values/styles.xml
================================================
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
================================================
FILE: demo/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: library/.gitignore
================================================
/build
================================================
FILE: library/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
version = "1.0.0"
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
resourcePrefix "missview__"
defaultConfig {
minSdkVersion 9
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile files('libs/picasso-2.1.1.jar')
}
def siteUrl = 'https://github.com/Rogero0o/MissView'
def gitUrl = 'https://github.com/Rogero0o/MissView.git'
group = "com.roger.missview.library"
install {
repositories.mavenInstaller {
// This generates POM.xml with proper parameters
pom {
project {
packaging 'aar'
// Add your description here
name 'Android MissView' //Ŀ
url siteUrl
// Set your license
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id 'roger' //дһЩϢ
name 'Jack'
email 'flyrogermail@gmail.com'
}
}
scm {
connection gitUrl
developerConnection gitUrl
url siteUrl
}
}
}
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives javadocJar
archives sourcesJar
}
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")
configurations = ['archives']
pkg {
repo = "maven"
name = "MissView"
websiteUrl = siteUrl
vcsUrl = gitUrl
licenses = ["Apache-2.0"]
publish = true
}
}
================================================
FILE: library/library.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":library" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="com.roger.missview.library" external.system.module.version="1.0.0" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":library" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="LIBRARY_PROJECT" value="true" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/docs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/mockable-android-21.jar" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/poms" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" scope="TEST" name="mockable-android-21" level="project" />
<orderEntry type="library" exported="" name="picasso-2.1.1" level="project" />
</component>
</module>
================================================
FILE: library/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in F:/adt-bundle-windows-x86_64_with_Android_5.0/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
================================================
FILE: library/src/androidTest/java/com/roger/missview/library/ApplicationTest.java
================================================
package com.roger.missview.library;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
================================================
FILE: library/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.roger.missview.library">
</manifest>
================================================
FILE: library/src/main/java/com/roger/missview/library/BlurRenderer.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import com.roger.missview.library.util.ArtDetailViewport;
import com.roger.missview.library.util.BitmapRegionLoader;
import com.roger.missview.library.util.ImageBlurrer;
import com.roger.missview.library.util.ImageUtil;
import com.roger.missview.library.util.MathUtil;
import com.roger.missview.library.util.TickingFloatAnimator;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class BlurRenderer implements GLSurfaceView.Renderer {
private static final int CROSSFADE_ANIMATION_DURATION = 750;
private static final int BLUR_ANIMATION_DURATION = 750;
public static final int DEFAULT_BLUR = 250; // max 500
public static final int DEFAULT_GREY = 0; // max 500
public static final int DEMO_DIM = 64;
public static final int DEFAULT_MAX_DIM = 128; // technical max 255
public static final float DIM_RANGE = 0.5f; // percent of max dim
private boolean mDemoMode;
private boolean mPreview;
private int mMaxPrescaledBlurPixels;
private int mBlurKeyframes = 3;
private int mBlurredSampleSize;
private int mMaxDim;
private int mMaxGrey;
// Model and view matrices. Projection and MVP stored in picture set
private final float[] mMMatrix = new float[16];
private final float[] mVMatrix = new float[16];
private Callbacks mCallbacks;
private float mAspectRatio;
private int mHeight;
private GLPictureSet mCurrentGLPictureSet;
private GLPictureSet mNextGLPictureSet;
private GLColorOverlay mColorOverlay;
private BitmapRegionLoader mQueuedNextBitmapRegionLoader;
private boolean mSurfaceCreated;
private volatile float mNormalOffsetX;
private volatile RectF mCurrentViewport = new RectF(); // [-1, -1] to [1, 1], flipped
private Context mContext;
private boolean mIsBlurred = true;
private boolean mBlurRelatedToArtDetailMode = false;
private Interpolator mBlurInterpolator = new AccelerateDecelerateInterpolator();
private TickingFloatAnimator mBlurAnimator;
private TickingFloatAnimator mCrossfadeAnimator = TickingFloatAnimator.create().from(0);
public BlurRenderer(Context context, Callbacks callbacks) {
mContext = context;
mCallbacks = callbacks;
mBlurKeyframes = getNumberOfKeyframes();
mBlurAnimator = TickingFloatAnimator.create().from(mBlurKeyframes);
mCurrentGLPictureSet = new GLPictureSet(0);
mNextGLPictureSet = new GLPictureSet(1); // for transitioning to next pictures
setNormalOffsetX(0);
recomputeMaxPrescaledBlurPixels();
recomputeMaxDimAmount();
recomputeGreyAmount();
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private int getNumberOfKeyframes() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ActivityManager activityManager = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
if (activityManager.isLowRamDevice()) {
return 1;
}
}
return 5;
}
public void recomputeMaxPrescaledBlurPixels() {
// Compute blur sizes
float maxBlurRadiusOverScreenHeight = PreferenceManager
.getDefaultSharedPreferences(mContext).getInt("blur_amount", DEFAULT_BLUR)
* 0.0001f;
DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
int maxBlurPx = (int) (dm.heightPixels * maxBlurRadiusOverScreenHeight);
mBlurredSampleSize = 4;
while (maxBlurPx / mBlurredSampleSize > ImageBlurrer.MAX_SUPPORTED_BLUR_PIXELS) {
mBlurredSampleSize <<= 1;
}
mMaxPrescaledBlurPixels = maxBlurPx / mBlurredSampleSize;
}
public void recomputeMaxDimAmount() {
mMaxDim = PreferenceManager
.getDefaultSharedPreferences(mContext).getInt("dim_amount", DEFAULT_MAX_DIM);
}
public void recomputeGreyAmount() {
mMaxGrey = PreferenceManager
.getDefaultSharedPreferences(mContext).getInt("grey_amount", DEFAULT_GREY);
}
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
mSurfaceCreated = false;
GLES20.glEnable(GLES20.GL_BLEND);
// GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glBlendFuncSeparate(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA,
GLES20.GL_ONE, GLES20.GL_ONE);
GLES20.glClearColor(0, 0, 0, 0);
// Set the camera position (View matrix)
Matrix.setLookAtM(mVMatrix, 0,
0, 0, 1,
0, 0, -1,
0, 1, 0);
GLColorOverlay.initGl();
GLPicture.initGl();
mColorOverlay = new GLColorOverlay(0);
mSurfaceCreated = true;
if (mQueuedNextBitmapRegionLoader != null) {
BitmapRegionLoader loader = mQueuedNextBitmapRegionLoader;
mQueuedNextBitmapRegionLoader = null;
setAndConsumeBitmapRegionLoader(loader);
}
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
hintViewportSize(width, height);
if (!mDemoMode && !mPreview) {
// Reset art detail viewports
ArtDetailViewport.getInstance().setViewport(0, 0, 0, 0, 0, false);
ArtDetailViewport.getInstance().setViewport(1, 0, 0, 0, 0, false);
}
mCurrentGLPictureSet.recomputeTransformMatrices();
mNextGLPictureSet.recomputeTransformMatrices();
recomputeMaxPrescaledBlurPixels();
}
public void hintViewportSize(int width, int height) {
mHeight = height;
mAspectRatio = width * 1f / height;
}
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setIdentityM(mMMatrix, 0);
boolean stillAnimating = mCrossfadeAnimator.tick();
stillAnimating |= mBlurAnimator.tick();
if (mBlurRelatedToArtDetailMode) {
mCurrentGLPictureSet.recomputeTransformMatrices();
mNextGLPictureSet.recomputeTransformMatrices();
}
float dimAmount = mCurrentGLPictureSet.mDimAmount;
mCurrentGLPictureSet.drawFrame(1);
if (mCrossfadeAnimator.isRunning()) {
dimAmount = MathUtil.interpolate(dimAmount, mNextGLPictureSet.mDimAmount,
mCrossfadeAnimator.currentValue());
mNextGLPictureSet.drawFrame(mCrossfadeAnimator.currentValue());
}
mColorOverlay.setColor(Color.argb((int) (dimAmount
* mBlurAnimator.currentValue() / mBlurKeyframes), 0, 0, 0));
mColorOverlay.draw(mMMatrix); // don't need any perspective or anything for color overlay
if (stillAnimating) {
mCallbacks.requestRender();
}
}
public void setNormalOffsetX(float x) {
mNormalOffsetX = MathUtil.constrain(0, 1, x);
onViewportChanged();
}
private void onViewportChanged() {
mCurrentGLPictureSet.recomputeTransformMatrices();
mNextGLPictureSet.recomputeTransformMatrices();
if (mSurfaceCreated) {
mCallbacks.requestRender();
}
}
private float blurRadiusAtFrame(float f) {
return mMaxPrescaledBlurPixels * mBlurInterpolator.getInterpolation(f / mBlurKeyframes);
}
public void setAndConsumeBitmapRegionLoader(final BitmapRegionLoader bitmapRegionLoader) {
if (!mSurfaceCreated) {
mQueuedNextBitmapRegionLoader = bitmapRegionLoader;
return;
}
if (mCrossfadeAnimator.isRunning()) {
if (mQueuedNextBitmapRegionLoader != null) {
mQueuedNextBitmapRegionLoader.destroy();
}
mQueuedNextBitmapRegionLoader = bitmapRegionLoader;
return;
}
mNextGLPictureSet.load(bitmapRegionLoader);
mCrossfadeAnimator
.from(0).to(1)
.withDuration(CROSSFADE_ANIMATION_DURATION)
.withEndListener(new Runnable() {
@Override
public void run() {
// swap current and next picturesets
final GLPictureSet oldGLPictureSet = mCurrentGLPictureSet;
mCurrentGLPictureSet = mNextGLPictureSet;
mNextGLPictureSet = new GLPictureSet(oldGLPictureSet.mId);
mCallbacks.requestRender();
oldGLPictureSet.destroyPictures();
System.gc();
if (mQueuedNextBitmapRegionLoader != null) {
BitmapRegionLoader queuedNextBitmapRegionLoader
= mQueuedNextBitmapRegionLoader;
mQueuedNextBitmapRegionLoader = null;
setAndConsumeBitmapRegionLoader(queuedNextBitmapRegionLoader);
}
}
})
.start();
mCallbacks.requestRender();
}
public void setDemoMode(boolean demoMode) {
mDemoMode = demoMode;
}
public void setIsPreview(boolean preview) {
mPreview = preview;
}
private class GLPictureSet {
private int mId;
private volatile float[] mPMatrix = new float[16];
private final float[] mMVPMatrix = new float[16];
private GLPicture[] mPictures = new GLPicture[mBlurKeyframes + 1];
private boolean mHasBitmap = false;
private float mBitmapAspectRatio = 1f;
private int mDimAmount = 0;
public GLPictureSet(int id) {
mId = id;
}
public void load(BitmapRegionLoader bitmapRegionLoader) {
mHasBitmap = (bitmapRegionLoader != null);
mBitmapAspectRatio = mHasBitmap
? bitmapRegionLoader.getWidth() * 1f / bitmapRegionLoader.getHeight()
: 1f;
mDimAmount = DEFAULT_MAX_DIM;
destroyPictures();
if (bitmapRegionLoader != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
Rect rect = new Rect();
int originalWidth = bitmapRegionLoader.getWidth();
int originalHeight = bitmapRegionLoader.getHeight();
// Calculate image darkness to determine dim amount
rect.set(0, 0, originalWidth, originalHeight);
options.inSampleSize = ImageUtil.calculateSampleSize(originalHeight, 64);
Bitmap tempBitmap = bitmapRegionLoader.decodeRegion(rect, options);
float darkness = ImageUtil.calculateDarkness(tempBitmap);
mDimAmount = mDemoMode
? DEMO_DIM
: (int) (mMaxDim * ((1 - DIM_RANGE) + DIM_RANGE * Math.sqrt(darkness)));
tempBitmap.recycle();
// Create the GLPicture objects
mPictures[0] = new GLPicture(bitmapRegionLoader, mHeight);
if (mMaxPrescaledBlurPixels == 0) {
for (int f = 1; f <= mBlurKeyframes; f++) {
mPictures[f] = mPictures[0];
}
} else {
ImageBlurrer blurrer = new ImageBlurrer(mContext);
// To blur, first load the entire bitmap region, but at a very large
// sample size that's appropriate for the final blurred image
options.inSampleSize = ImageUtil.calculateSampleSize(
originalHeight, mHeight / mBlurredSampleSize);
rect.set(0, 0, originalWidth, originalHeight);
tempBitmap = bitmapRegionLoader.decodeRegion(rect, options);
// Next, create a scaled down version of the bitmap so that the blur radius
// looks appropriate (tempBitmap will likely be bigger than the final blurred
// bitmap, and thus the blur may look smaller if we just used tempBitmap as
// the final blurred bitmap).
// Note that image width should be a multiple of 4 to avoid
// issues with RenderScript allocations.
int scaledHeight = Math.max(2, MathUtil.floorEven(
mHeight / mBlurredSampleSize));
int scaledWidth = Math.max(4, MathUtil.roundMult4(
(int) (scaledHeight * mBitmapAspectRatio)));
Bitmap scaledBitmap = Bitmap.createScaledBitmap(
tempBitmap, scaledWidth, scaledHeight, true);
tempBitmap.recycle();
// And finally, create a blurred copy for each keyframe.
for (int f = 1; f <= mBlurKeyframes; f++) {
float desaturateAmount = mMaxGrey / 500f * f / mBlurKeyframes;
Bitmap blurredBitmap = blurrer.blurBitmap(
scaledBitmap, blurRadiusAtFrame(f), desaturateAmount);
mPictures[f] = new GLPicture(blurredBitmap);
blurredBitmap.recycle();
}
scaledBitmap.recycle();
blurrer.destroy();
}
}
recomputeTransformMatrices();
mCallbacks.requestRender();
}
private void recomputeTransformMatrices() {
float screenToBitmapAspectRatio = mAspectRatio / mBitmapAspectRatio;
// Ensure the bitmap is wider than the screen relatively by applying zoom
// if necessary. Vary width but keep height the same.
float zoom = Math.max(1f, 1.15f * screenToBitmapAspectRatio);
// Total scale factors in both zoom and scale due to aspect ratio.
float totalScale = zoom / screenToBitmapAspectRatio;
mCurrentViewport.left = MathUtil.interpolate(
-1f * Math.min(1f, screenToBitmapAspectRatio), // remove screenToBitmapAspectRatio to unconstrain panning amount
1f * Math.min(1f, screenToBitmapAspectRatio),
mNormalOffsetX * (totalScale - 1) / totalScale);
mCurrentViewport.right = mCurrentViewport.left + 2f / totalScale;
mCurrentViewport.bottom = -1f / zoom;
mCurrentViewport.top = 1f / zoom;
float focusAmount = (mBlurKeyframes - mBlurAnimator.currentValue()) / mBlurKeyframes;
if (mBlurRelatedToArtDetailMode && focusAmount > 0) {
RectF artDetailViewport = ArtDetailViewport.getInstance().getViewport(mId);
if (artDetailViewport.width() == 0 || artDetailViewport.height() == 0) {
if (!mDemoMode && !mPreview) {
// reset art detail viewport
ArtDetailViewport.getInstance().setViewport(mId,
MathUtil.uninterpolate(-1, 1, mCurrentViewport.left),
MathUtil.uninterpolate(1, -1, mCurrentViewport.top),
MathUtil.uninterpolate(-1, 1, mCurrentViewport.right),
MathUtil.uninterpolate(1, -1, mCurrentViewport.bottom),
false);
}
} else {
// interpolate
mCurrentViewport.left = MathUtil.interpolate(
mCurrentViewport.left,
MathUtil.interpolate(-1, 1, artDetailViewport.left),
focusAmount);
mCurrentViewport.top = MathUtil.interpolate(
mCurrentViewport.top,
MathUtil.interpolate(1, -1, artDetailViewport.top),
focusAmount);
mCurrentViewport.right = MathUtil.interpolate(
mCurrentViewport.right,
MathUtil.interpolate(-1, 1, artDetailViewport.right),
focusAmount);
mCurrentViewport.bottom = MathUtil.interpolate(
mCurrentViewport.bottom,
MathUtil.interpolate(1, -1, artDetailViewport.bottom),
focusAmount);
}
}
Matrix.orthoM(mPMatrix, 0,
mCurrentViewport.left, mCurrentViewport.right,
mCurrentViewport.bottom, mCurrentViewport.top,
1, 10);
}
public void drawFrame(float globalAlpha) {
if (!mHasBitmap) {
return;
}
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mPMatrix, 0, mMVPMatrix, 0);
float blurFrame = mBlurAnimator.currentValue();
int lo = (int) Math.floor(blurFrame);
int hi = (int) Math.ceil(blurFrame);
float localHiAlpha = (blurFrame - lo);
if (globalAlpha <= 0) {
// Nothing to draw
} else if (lo == hi) {
// Just draw one
mPictures[lo].draw(mMVPMatrix, globalAlpha);
} else if (globalAlpha == 1) {
// Simple drawing
mPictures[lo].draw(mMVPMatrix, 1);
mPictures[hi].draw(mMVPMatrix, localHiAlpha);
} else {
// If there's both a global and local alpha, re-compose alphas, to
// effectively compose hi and lo before composing the result
// with the background.
//
// The math, where a1,a2 are previous alphas and b1,b2 are new alphas:
// b1 = a1 * (a2 - 1) / (a1 * a2 - 1)
// b2 = a1 * a2
float newLocalLoAlpha = globalAlpha * (localHiAlpha - 1)
/ (globalAlpha * localHiAlpha - 1);
float newLocalHiAlpha = globalAlpha * localHiAlpha;
mPictures[lo].draw(mMVPMatrix, newLocalLoAlpha);
mPictures[hi].draw(mMVPMatrix, newLocalHiAlpha);
}
}
public void destroyPictures() {
for (int i = 0; i < mPictures.length; i++) {
if (mPictures[i] == null) {
continue;
}
mPictures[i].destroy();
mPictures[i] = null;
}
}
}
public void destroy() {
mCurrentGLPictureSet.destroyPictures();
mNextGLPictureSet.destroyPictures();
}
public boolean isBlurred() {
return mIsBlurred;
}
public void setIsBlurred(final boolean isBlurred, final boolean artDetailMode) {
if (artDetailMode && !isBlurred && !mDemoMode && !mPreview) {
// Reset art detail viewport
ArtDetailViewport.getInstance().setViewport(0, 0, 0, 0, 0, false);
ArtDetailViewport.getInstance().setViewport(1, 0, 0, 0, 0, false);
}
mBlurRelatedToArtDetailMode = artDetailMode;
mIsBlurred = isBlurred;
mBlurAnimator.cancel();
mBlurAnimator
.to(isBlurred ? mBlurKeyframes : 0)
.withDuration(BLUR_ANIMATION_DURATION * (mDemoMode ? 5 : 1))
.withEndListener(new Runnable() {
@Override
public void run() {
if (isBlurred && artDetailMode) {
System.gc();
}
}
})
.start();
mCallbacks.requestRender();
}
public static interface Callbacks {
void requestRender();
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/DemoRenderController.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import com.roger.missview.library.util.BitmapRegionLoader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class DemoRenderController extends RenderController {
private final Handler mHandler = new Handler();
private static final long ANIMATION_CYCLE_TIME_MILLIS = 35000;
private static final long FOCUS_DELAY_TIME_MILLIS = 2000;
private static final long FOCUS_TIME_MILLIS = 6000;
private Animator mCurrentScrollAnimator;
private boolean mReverseDirection = false;
private boolean mAllowFocus = true;
private String mPictureName;
private Bitmap mBitmap;
public DemoRenderController(Context context, BlurRenderer renderer, Callbacks callbacks,
boolean allowFocus, String mPictureName) {
super(context, renderer, callbacks);
mAllowFocus = allowFocus;
this.mPictureName = mPictureName;
runAnimation();
}
public DemoRenderController(Context context, BlurRenderer renderer, Callbacks callbacks,
boolean allowFocus, Bitmap mBitmap) {
super(context, renderer, callbacks);
mAllowFocus = allowFocus;
this.mBitmap = mBitmap;
runAnimation();
}
private void runAnimation() {
if (mCurrentScrollAnimator != null) {
mCurrentScrollAnimator.cancel();
}
mCurrentScrollAnimator =
ObjectAnimator.ofFloat(mRenderer, "normalOffsetX", mReverseDirection ? 1f : 0f,
mReverseDirection ? 0f : 1f).setDuration(ANIMATION_CYCLE_TIME_MILLIS);
mCurrentScrollAnimator.start();
mCurrentScrollAnimator.addListener(new AnimatorListenerAdapter() {
@Override public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mReverseDirection = !mReverseDirection;
runAnimation();
}
});
if (mAllowFocus) {
mHandler.postDelayed(new Runnable() {
@Override public void run() {
mRenderer.setIsBlurred(false, false);
mHandler.postDelayed(new Runnable() {
@Override public void run() {
mRenderer.setIsBlurred(true, false);
}
}, FOCUS_TIME_MILLIS);
}
}, FOCUS_DELAY_TIME_MILLIS);
}
}
@Override public void destroy() {
super.destroy();
if (mCurrentScrollAnimator != null) {
mCurrentScrollAnimator.cancel();
}
mHandler.removeCallbacksAndMessages(null);
}
@Override protected BitmapRegionLoader openDownloadedCurrentArtwork(boolean forceReload) {
try {
if (mBitmap != null) {
return BitmapRegionLoader.newInstance(Bitmap2IS(mBitmap));
} else if (mPictureName != null) {
InputStream m = new FileInputStream(mPictureName);
return BitmapRegionLoader.newInstance(m);
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
return null;
}
private InputStream Bitmap2IS(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
InputStream sbs = new ByteArrayInputStream(baos.toByteArray());
return sbs;
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/GLColorOverlay.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library;
import android.graphics.Color;
import android.opengl.GLES20;
import java.nio.FloatBuffer;
class GLColorOverlay {
private static final String VERTEX_SHADER_CODE = "" +
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 aPosition;" +
"void main(){" +
" gl_Position = uMVPMatrix * aPosition;" +
"}";
private static final String FRAGMENT_SHADER_CODE = "" +
"precision mediump float;" +
"uniform sampler2D uTexture;" +
"uniform vec4 uColor;" +
"void main(){" +
" gl_FragColor = uColor;" +
"}";
// number of coordinates per vertex in this array
private static final int COORDS_PER_VERTEX = 3;
private static final int VERTEX_STRIDE_BYTES = COORDS_PER_VERTEX * GLUtil.BYTES_PER_FLOAT;
private float mVertices[] = {
-1, 1, 0, // top left
-1, -1, 0, // bottom left
1, -1, 0, // bottom right
-1, 1, 0, // top left
1, -1, 0, // bottom right
1, 1, 0, // top right
};
private int mColor;
private FloatBuffer mVertexBuffer;
private static int sProgramHandle;
private static int sAttribPositionHandle;
private static int sUniformColorHandle;
private static int sUniformMVPMatrixHandle;
public GLColorOverlay(int color) {
mColor = color;
mVertexBuffer = GLUtil.asFloatBuffer(mVertices);
}
public static void initGl() {
// Initialize shaders and create/link program
int vertexShaderHandle = GLUtil.loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_CODE);
int fragShaderHandle = GLUtil.loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE);
sProgramHandle = GLUtil.createAndLinkProgram(vertexShaderHandle, fragShaderHandle, null);
sAttribPositionHandle = GLES20.glGetAttribLocation(sProgramHandle, "aPosition");
sUniformMVPMatrixHandle = GLES20.glGetUniformLocation(sProgramHandle, "uMVPMatrix");
sUniformColorHandle = GLES20.glGetUniformLocation(sProgramHandle, "uColor");
}
public void draw(float[] mvpMatrix) {
// Add program to OpenGL ES environment
GLES20.glUseProgram(sProgramHandle);
// Pass in the vertex information
GLES20.glEnableVertexAttribArray(sAttribPositionHandle);
GLES20.glVertexAttribPointer(sAttribPositionHandle,
COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
VERTEX_STRIDE_BYTES, mVertexBuffer);
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(sUniformMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLUtil.checkGlError("glUniformMatrix4fv");
// Set the alpha
float r = Color.red(mColor) * 1f / 255;
float g = Color.green(mColor) * 1f / 255;
float b = Color.blue(mColor) * 1f / 255;
float a = Color.alpha(mColor) * 1f / 255;
GLES20.glUniform4f(sUniformColorHandle, r, g, b, a);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertices.length / COORDS_PER_VERTEX);
GLES20.glDisableVertexAttribArray(sAttribPositionHandle);
}
public void setColor(int color) {
mColor = color;
}
public void destroy() {
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/GLPicture.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.opengl.GLES20;
import com.roger.missview.library.util.BitmapRegionLoader;
import java.nio.FloatBuffer;
class GLPicture {
private static final String VERTEX_SHADER_CODE = "" +
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 aPosition;" +
"attribute vec2 aTexCoords;" +
"varying vec2 vTexCoords;" +
"void main(){" +
" vTexCoords = aTexCoords;" +
" gl_Position = uMVPMatrix * aPosition;" +
"}";
private static final String FRAGMENT_SHADER_CODE = "" +
"precision mediump float;" +
"uniform sampler2D uTexture;" +
"uniform float uAlpha;" +
"varying vec2 vTexCoords;" +
"void main(){" +
" gl_FragColor = texture2D(uTexture, vTexCoords);" +
" gl_FragColor.a = uAlpha;" +
"}";
// number of coordinates per vertex in this array
private static final int COORDS_PER_VERTEX = 3;
private static final int VERTEX_STRIDE_BYTES = COORDS_PER_VERTEX * GLUtil.BYTES_PER_FLOAT;
private static final int VERTICES = 6; // TL, BL, BR, TL, BR, TR
// S, T (or X, Y)
private static final int COORDS_PER_TEXTURE_VERTEX = 2;
private static final int TEXTURE_VERTEX_STRIDE_BYTES = COORDS_PER_TEXTURE_VERTEX
* GLUtil.BYTES_PER_FLOAT;
private static final float[] SQUARE_TEXTURE_VERTICES = {
0, 0, // top left
0, 1, // bottom left
1, 1, // bottom right
0, 0, // top left
1, 1, // bottom right
1, 0, // top right
};
private boolean mHasContent = false;
private float[] mVertices = new float[COORDS_PER_VERTEX * VERTICES];
private FloatBuffer mVertexBuffer;
private FloatBuffer mTextureCoordsBuffer;
private static int sMaxTextureSize;
private static int sProgramHandle;
private static int sAttribPositionHandle;
private static int sAttribTextureCoordsHandle;
private static int sUniformAlphaHandle;
private static int sUniformTextureHandle;
private static int sUniformMVPMatrixHandle;
private int mCols = 1;
private int mRows = 1;
private int mWidth = 0;
private int mHeight = 0;
private int mTileSize = sMaxTextureSize;
private int[] mTextureHandles;
public static void initGl() {
// Initialize shaders and create/link program
int vertexShaderHandle = GLUtil.loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_CODE);
int fragShaderHandle = GLUtil.loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE);
sProgramHandle = GLUtil.createAndLinkProgram(vertexShaderHandle, fragShaderHandle, null);
sAttribPositionHandle = GLES20.glGetAttribLocation(sProgramHandle, "aPosition");
sAttribTextureCoordsHandle = GLES20.glGetAttribLocation(sProgramHandle, "aTexCoords");
sUniformMVPMatrixHandle = GLES20.glGetUniformLocation(sProgramHandle, "uMVPMatrix");
sUniformTextureHandle = GLES20.glGetUniformLocation(sProgramHandle, "uTexture");
sUniformAlphaHandle = GLES20.glGetUniformLocation(sProgramHandle, "uAlpha");
// Compute max texture size
int[] maxTextureSize = new int[1];
GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
sMaxTextureSize = maxTextureSize[0];
}
public GLPicture(BitmapRegionLoader bitmapRegionLoader, int maxHeight) {
if (bitmapRegionLoader == null || maxHeight == 0) {
return;
}
mHasContent = true;
mVertexBuffer = GLUtil.newFloatBuffer(mVertices.length);
mTextureCoordsBuffer = GLUtil.asFloatBuffer(SQUARE_TEXTURE_VERTICES);
int originalWidth = bitmapRegionLoader.getWidth();
int originalHeight = bitmapRegionLoader.getHeight();
int sampleSize = 1;
while (originalHeight / (sampleSize << 1) > maxHeight) {
sampleSize <<= 1;
}
mWidth = originalWidth / sampleSize;
mHeight = originalHeight / sampleSize;
mTileSize = Math.min(512, sMaxTextureSize);
int unsampledTileSize = mTileSize * sampleSize;
int leftoverHeight = originalHeight % unsampledTileSize;
// Load m x n textures
mCols = mWidth / (mTileSize + 1) + 1;
mRows = mHeight / (mTileSize + 1) + 1;
mTextureHandles = new int[mCols * mRows];
Bitmap tileBitmap = Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888);
Rect rect = new Rect();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
options.inBitmap = tileBitmap;
for (int y = 0; y < mRows; y++) {
for (int x = 0; x < mCols; x++) {
rect.set(x * unsampledTileSize,
(mRows - y - 1) * unsampledTileSize,
(x + 1) * unsampledTileSize,
(mRows - y) * unsampledTileSize);
// The bottom tiles must be full tiles for drawing, so only allow edge tiles
// at the top
if (leftoverHeight > 0) {
rect.offset(0, -unsampledTileSize + leftoverHeight);
}
rect.intersect(0, 0, originalWidth, originalHeight);
Bitmap useBitmap = bitmapRegionLoader.decodeRegion(rect, options);
mTextureHandles[y * mCols + x] = GLUtil.loadTexture(useBitmap);
if (useBitmap != tileBitmap) {
useBitmap.recycle();
}
}
}
}
public GLPicture(Bitmap bitmap) {
if (bitmap == null) {
return;
}
mTileSize = sMaxTextureSize;
mHasContent = true;
mVertexBuffer = GLUtil.newFloatBuffer(mVertices.length);
mTextureCoordsBuffer = GLUtil.asFloatBuffer(SQUARE_TEXTURE_VERTICES);
mWidth = bitmap.getWidth();
mHeight = bitmap.getHeight();
int leftoverHeight = mHeight % mTileSize;
// Load m x n textures
mCols = mWidth / (mTileSize + 1) + 1;
mRows = mHeight / (mTileSize + 1) + 1;
mTextureHandles = new int[mCols * mRows];
if (mCols == 1 && mRows == 1) {
mTextureHandles[0] = GLUtil.loadTexture(bitmap);
} else {
Rect rect = new Rect();
for (int y = 0; y < mRows; y++) {
for (int x = 0; x < mCols; x++) {
rect.set(x * mTileSize,
(mRows - y - 1) * mTileSize,
(x + 1) * mTileSize,
(mRows - y) * mTileSize);
// The bottom tiles must be full tiles for drawing, so only allow edge tiles
// at the top
if (leftoverHeight > 0) {
rect.offset(0, -mTileSize + leftoverHeight);
}
rect.intersect(0, 0, mWidth, mHeight);
Bitmap subBitmap = Bitmap.createBitmap(bitmap,
rect.left, rect.top, rect.width(), rect.height());
mTextureHandles[y * mCols + x] = GLUtil.loadTexture(subBitmap);
subBitmap.recycle();
}
}
}
}
public void draw(float[] mvpMatrix, float alpha) {
if (!mHasContent) {
return;
}
// Add program to OpenGL ES environment
GLES20.glUseProgram(sProgramHandle);
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(sUniformMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLUtil.checkGlError("glUniformMatrix4fv");
// Set up vertex buffer
GLES20.glEnableVertexAttribArray(sAttribPositionHandle);
GLES20.glVertexAttribPointer(sAttribPositionHandle,
COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
VERTEX_STRIDE_BYTES, mVertexBuffer);
// Set up texture stuff
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glUniform1i(sUniformTextureHandle, 0);
GLES20.glVertexAttribPointer(sAttribTextureCoordsHandle,
COORDS_PER_TEXTURE_VERTEX, GLES20.GL_FLOAT, false,
TEXTURE_VERTEX_STRIDE_BYTES, mTextureCoordsBuffer);
GLES20.glEnableVertexAttribArray(sAttribTextureCoordsHandle);
// Set the alpha
GLES20.glUniform1f(sUniformAlphaHandle, alpha);
// Draw tiles
for (int y = 0; y < mRows; y++) {
for (int x = 0; x < mCols; x++) {
// Pass in the vertex information
mVertices[0] = mVertices[3] = mVertices[9]
= Math.min(-1 + 2f * x * mTileSize / mWidth, 1); // left
mVertices[1] = mVertices[10] = mVertices[16]
= Math.min(-1 + 2f * (y + 1) * mTileSize / mHeight, 1); // top
mVertices[6] = mVertices[12] = mVertices[15]
= Math.min(-1 + 2f * (x + 1) * mTileSize / mWidth, 1); // right
mVertices[4] = mVertices[7] = mVertices[13]
= Math.min(-1 + 2f * y * mTileSize / mHeight, 1); // bottom
mVertexBuffer.put(mVertices);
mVertexBuffer.position(0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,
mTextureHandles[y * mCols + x]);
GLUtil.checkGlError("glBindTexture");
// Draw the two triangles
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertices.length / COORDS_PER_VERTEX);
}
}
GLES20.glDisableVertexAttribArray(sAttribPositionHandle);
GLES20.glDisableVertexAttribArray(sAttribTextureCoordsHandle);
}
public void destroy() {
if (mTextureHandles != null) {
GLES20.glDeleteTextures(mTextureHandles.length, mTextureHandles, 0);
GLUtil.checkGlError("Destroy picture");
mTextureHandles = null;
}
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/GLTextureView.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.opengl.GLDebugHelper;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.TextureView;
import java.io.Writer;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGL11;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
/**
* See http://stackoverflow.com/questions/12061419/converting-from-glsurfaceview-to-textureview-via-gltextureview
*/
public class GLTextureView extends TextureView implements TextureView.SurfaceTextureListener {
private final static String TAG = "GLTextureView";
private final static boolean LOG_ATTACH_DETACH = false;
private final static boolean LOG_THREADS = false;
private final static boolean LOG_PAUSE_RESUME = false;
private final static boolean LOG_SURFACE = false;
private final static boolean LOG_RENDERER = false;
private final static boolean LOG_RENDERER_DRAW_FRAME = false;
private final static boolean LOG_EGL = false;
/**
* The renderer only renders
* when the surface is created, or when {@link #requestRender} is called.
*
* @see #getRenderMode()
* @see #setRenderMode(int)
* @see #requestRender()
*/
public final static int RENDERMODE_WHEN_DIRTY = 0;
/**
* The renderer is called
* continuously to re-render the scene.
*
* @see #getRenderMode()
* @see #setRenderMode(int)
*/
public final static int RENDERMODE_CONTINUOUSLY = 1;
/**
* Check glError() after every GL call and throw an exception if glError indicates
* that an error has occurred. This can be used to help track down which OpenGL ES call
* is causing an error.
*
* @see #getDebugFlags
* @see #setDebugFlags
*/
public final static int DEBUG_CHECK_GL_ERROR = 1;
/**
* Log GL calls to the system log at "verbose" level with tag "GLSurfaceView".
*
* @see #getDebugFlags
* @see #setDebugFlags
*/
public final static int DEBUG_LOG_GL_CALLS = 2;
/**
* Standard View constructor. In order to render something, you
* must call {@link #setRenderer} to register a renderer.
*/
public GLTextureView(Context context) {
super(context);
init();
}
/**
* Standard View constructor. In order to render something, you
* must call {@link #setRenderer} to register a renderer.
*/
public GLTextureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
@Override
protected void finalize() throws Throwable {
try {
if (mGLThread != null) {
// GLThread may still be running if this view was never
// attached to a window.
mGLThread.requestExitAndWait();
}
} finally {
super.finalize();
}
}
private void init() {
setSurfaceTextureListener(this);
}
/**
* Set the glWrapper. If the glWrapper is not null, its
* {@link GLWrapper#wrap(javax.microedition.khronos.opengles.GL)} method is called
* whenever a surface is created. A GLWrapper can be used to wrap
* the GL object that's passed to the renderer. Wrapping a GL
* object enables examining and modifying the behavior of the
* GL calls made by the renderer.
* <p>
* Wrapping is typically used for debugging purposes.
* <p>
* The default value is null.
* @param glWrapper the new GLWrapper
*/
public void setGLWrapper(GLWrapper glWrapper) {
mGLWrapper = glWrapper;
}
/**
* Set the debug flags to a new value. The value is
* constructed by OR-together zero or more
* of the DEBUG_CHECK_* constants. The debug flags take effect
* whenever a surface is created. The default value is zero.
* @param debugFlags the new debug flags
* @see #DEBUG_CHECK_GL_ERROR
* @see #DEBUG_LOG_GL_CALLS
*/
public void setDebugFlags(int debugFlags) {
mDebugFlags = debugFlags;
}
/**
* Get the current value of the debug flags.
* @return the current value of the debug flags.
*/
public int getDebugFlags() {
return mDebugFlags;
}
/**
* Control whether the EGL context is preserved when the GLSurfaceView is paused and
* resumed.
* <p>
* If set to true, then the EGL context may be preserved when the GLSurfaceView is paused.
* Whether the EGL context is actually preserved or not depends upon whether the
* Android device that the program is running on can support an arbitrary number of EGL
* contexts or not. Devices that can only support a limited number of EGL contexts must
* release the EGL context in order to allow multiple applications to share the GPU.
* <p>
* If set to false, the EGL context will be released when the GLSurfaceView is paused,
* and recreated when the GLSurfaceView is resumed.
* <p>
*
* The default is false.
*
* @param preserveOnPause preserve the EGL context when paused
*/
public void setPreserveEGLContextOnPause(boolean preserveOnPause) {
mPreserveEGLContextOnPause = preserveOnPause;
}
/**
* @return true if the EGL context will be preserved when paused
*/
public boolean getPreserveEGLContextOnPause() {
return mPreserveEGLContextOnPause;
}
/**
* Set the renderer associated with this view. Also starts the thread that
* will call the renderer, which in turn causes the rendering to start.
* <p>This method should be called once and only once in the life-cycle of
* a GLSurfaceView.
* <p>The following GLSurfaceView methods can only be called <em>before</em>
* setRenderer is called:
* <ul>
* <li>{@link #setEGLConfigChooser(boolean)}
* <li>{@link #setEGLConfigChooser(EGLConfigChooser)}
* <li>{@link #setEGLConfigChooser(int, int, int, int, int, int)}
* </ul>
* <p>
* The following GLSurfaceView methods can only be called <em>after</em>
* setRenderer is called:
* <ul>
* <li>{@link #getRenderMode()}
* <li>{@link #onPause()}
* <li>{@link #onResume()}
* <li>{@link #queueEvent(Runnable)}
* <li>{@link #requestRender()}
* <li>{@link #setRenderMode(int)}
* </ul>
*
* @param renderer the renderer to use to perform OpenGL drawing.
*/
public void setRenderer(GLSurfaceView.Renderer renderer) {
checkRenderThreadState();
if (mEGLConfigChooser == null) {
mEGLConfigChooser = new SimpleEGLConfigChooser(true);
}
if (mEGLContextFactory == null) {
mEGLContextFactory = new DefaultContextFactory();
}
if (mEGLWindowSurfaceFactory == null) {
mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
}
mRenderer = renderer;
mGLThread = new GLThread(mThisWeakRef);
mGLThread.start();
}
/**
* Install a custom EGLContextFactory.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>
* If this method is not called, then by default
* a context will be created with no shared context and
* with a null attribute list.
*/
public void setEGLContextFactory(EGLContextFactory factory) {
checkRenderThreadState();
mEGLContextFactory = factory;
}
/**
* Install a custom EGLWindowSurfaceFactory.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>
* If this method is not called, then by default
* a window surface will be created with a null attribute list.
*/
public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {
checkRenderThreadState();
mEGLWindowSurfaceFactory = factory;
}
/**
* Install a custom EGLConfigChooser.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>
* If no setEGLConfigChooser method is called, then by default the
* view will choose an EGLConfig that is compatible with the current
* android.view.Surface, with a depth buffer depth of
* at least 16 bits.
* @param configChooser
*/
public void setEGLConfigChooser(EGLConfigChooser configChooser) {
checkRenderThreadState();
mEGLConfigChooser = configChooser;
}
/**
* Install a config chooser which will choose a config
* as close to 16-bit RGB as possible, with or without an optional depth
* buffer as close to 16-bits as possible.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>
* If no setEGLConfigChooser method is called, then by default the
* view will choose an RGB_888 surface with a depth buffer depth of
* at least 16 bits.
*
* @param needDepth
*/
public void setEGLConfigChooser(boolean needDepth) {
setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));
}
/**
* Install a config chooser which will choose a config
* with at least the specified depthSize and stencilSize,
* and exactly the specified redSize, greenSize, blueSize and alphaSize.
* <p>If this method is
* called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>
* If no setEGLConfigChooser method is called, then by default the
* view will choose an RGB_888 surface with a depth buffer depth of
* at least 16 bits.
*
*/
public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
int alphaSize, int depthSize, int stencilSize) {
setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize,
blueSize, alphaSize, depthSize, stencilSize));
}
/**
* Inform the default EGLContextFactory and default EGLConfigChooser
* which EGLContext client version to pick.
* <p>Use this method to create an OpenGL ES 2.0-compatible context.
* Example:
* <pre class="prettyprint">
* public MyView(Context context) {
* super(context);
* setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.
* setRenderer(new MyRenderer());
* }
* </pre>
* <p>Note: Activities which require OpenGL ES 2.0 should indicate this by
* setting @lt;uses-feature android:glEsVersion="0x00020000" in the activity's
* AndroidManifest.xml file.
* <p>If this method is called, it must be called before {@link #setRenderer(Renderer)}
* is called.
* <p>This method only affects the behavior of the default EGLContexFactory and the
* default EGLConfigChooser. If
* {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied
* EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context.
* If
* {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied
* EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config.
* @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0
*/
public void setEGLContextClientVersion(int version) {
checkRenderThreadState();
mEGLContextClientVersion = version;
}
/**
* Set the rendering mode. When renderMode is
* RENDERMODE_CONTINUOUSLY, the renderer is called
* repeatedly to re-render the scene. When renderMode
* is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface
* is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY.
* <p>
* Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance
* by allowing the GPU and CPU to idle when the view does not need to be updated.
* <p>
* This method can only be called after {@link #setRenderer(Renderer)}
*
* @param renderMode one of the RENDERMODE_X constants
* @see #RENDERMODE_CONTINUOUSLY
* @see #RENDERMODE_WHEN_DIRTY
*/
public void setRenderMode(int renderMode) {
mGLThread.setRenderMode(renderMode);
}
/**
* Get the current rendering mode. May be called
* from any thread. Must not be called before a renderer has been set.
* @return the current rendering mode.
* @see #RENDERMODE_CONTINUOUSLY
* @see #RENDERMODE_WHEN_DIRTY
*/
public int getRenderMode() {
return mGLThread.getRenderMode();
}
/**
* Request that the renderer render a frame.
* This method is typically used when the render mode has been set to
* {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand.
* May be called
* from any thread. Must not be called before a renderer has been set.
*/
public void requestRender() {
mGLThread.requestRender();
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
mGLThread.surfaceCreated();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
mGLThread.onWindowResize(width, height);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mGLThread.onWindowResize(w, h);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
mGLThread.surfaceDestroyed();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
requestRender();
}
/**
* This method is part of the SurfaceHolder.Callback interface, and is
* not normally called or subclassed by clients of GLSurfaceView.
*/
public void on(SurfaceHolder holder) {
mGLThread.surfaceCreated();
}
/**
* Inform the view that the activity is paused. The owner of this view must
* call this method when the activity is paused. Calling this method will
* pause the rendering thread.
* Must not be called before a renderer has been set.
*/
public void onPause() {
mGLThread.onPause();
}
/**
* Inform the view that the activity is resumed. The owner of this view must
* call this method when the activity is resumed. Calling this method will
* recreate the OpenGL display and resume the rendering
* thread.
* Must not be called before a renderer has been set.
*/
public void onResume() {
mGLThread.onResume();
}
/**
* Queue a runnable to be run on the GL rendering thread. This can be used
* to communicate with the Renderer on the rendering thread.
* Must not be called before a renderer has been set.
* @param r the runnable to be run on the GL rendering thread.
*/
public void queueEvent(Runnable r) {
mGLThread.queueEvent(r);
}
/**
* This method is used as part of the View class and is not normally
* called or subclassed by clients of GLSurfaceView.
*/
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (LOG_ATTACH_DETACH) {
Log.d(TAG, "onAttachedToWindow reattach =" + mDetached);
}
if (mDetached && (mRenderer != null)) {
int renderMode = RENDERMODE_CONTINUOUSLY;
if (mGLThread != null) {
renderMode = mGLThread.getRenderMode();
}
mGLThread = new GLThread(mThisWeakRef);
if (renderMode != RENDERMODE_CONTINUOUSLY) {
mGLThread.setRenderMode(renderMode);
}
mGLThread.start();
}
mDetached = false;
}
/**
* This method is used as part of the View class and is not normally
* called or subclassed by clients of GLSurfaceView.
* Must not be called before a renderer has been set.
*/
@Override
protected void onDetachedFromWindow() {
if (LOG_ATTACH_DETACH) {
Log.d(TAG, "onDetachedFromWindow");
}
if (mGLThread != null) {
mGLThread.requestExitAndWait();
}
mDetached = true;
super.onDetachedFromWindow();
}
// ----------------------------------------------------------------------
/**
* An interface used to wrap a GL interface.
* <p>Typically
* used for implementing debugging and tracing on top of the default
* GL interface. You would typically use this by creating your own class
* that implemented all the GL methods by delegating to another GL instance.
* Then you could add your own behavior before or after calling the
* delegate. All the GLWrapper would do was instantiate and return the
* wrapper GL instance:
* <pre class="prettyprint">
* class MyGLWrapper implements GLWrapper {
* GL wrap(GL gl) {
* return new MyGLImplementation(gl);
* }
* static class MyGLImplementation implements GL,GL10,GL11,... {
* ...
* }
* }
* </pre>
* @see #setGLWrapper(GLWrapper)
*/
public interface GLWrapper {
/**
* Wraps a gl interface in another gl interface.
* @param gl a GL interface that is to be wrapped.
* @return either the input argument or another GL object that wraps the input argument.
*/
GL wrap(GL gl);
}
/**
* An interface for customizing the eglCreateContext and eglDestroyContext calls.
* <p>
* This interface must be implemented by clients wishing to call
*
*/
public interface EGLContextFactory {
EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig);
void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
}
private class DefaultContextFactory implements EGLContextFactory {
private int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion,
EGL10.EGL_NONE };
return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT,
mEGLContextClientVersion != 0 ? attrib_list : null);
}
public void destroyContext(EGL10 egl, EGLDisplay display,
EGLContext context) {
if (!egl.eglDestroyContext(display, context)) {
Log.e("DefaultContextFactory", "display:" + display + " context: " + context);
if (LOG_THREADS) {
Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId());
}
EglHelper.throwEglException("eglDestroyContex", egl.eglGetError());
}
}
}
/**
* An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls.
* <p>
* This interface must be implemented by clients wishing to call
*
*/
public interface EGLWindowSurfaceFactory {
/**
* @return null if the surface cannot be constructed.
*/
EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config,
Object nativeWindow);
void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface);
}
private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
EGLConfig config, Object nativeWindow) {
EGLSurface result = null;
try {
result = egl.eglCreateWindowSurface(display, config, nativeWindow, null);
} catch (IllegalArgumentException e) {
// This exception indicates that the surface flinger surface
// is not valid. This can happen if the surface flinger surface has
// been torn down, but the application has not yet been
// notified via SurfaceHolder.Callback.surfaceDestroyed.
// In theory the application should be notified first,
// but in practice sometimes it is not. See b/4588890
Log.e(TAG, "eglCreateWindowSurface", e);
}
return result;
}
public void destroySurface(EGL10 egl, EGLDisplay display,
EGLSurface surface) {
egl.eglDestroySurface(display, surface);
}
}
/**
* An interface for choosing an EGLConfig configuration from a list of
* potential configurations.
* <p>
* This interface must be implemented by clients wishing to call
*
*/
public interface EGLConfigChooser {
/**
* Choose a configuration from the list. Implementors typically
* implement this method by calling
* {@link javax.microedition.khronos.egl.EGL10#eglChooseConfig} and iterating through the results. Please consult the
* EGL specification available from The Khronos Group to learn how to call eglChooseConfig.
* @param egl the EGL10 for the current display.
* @param display the current display.
* @return the chosen configuration.
*/
EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
}
private abstract class BaseConfigChooser
implements EGLConfigChooser {
public BaseConfigChooser(int[] configSpec) {
mConfigSpec = filterConfigSpec(configSpec);
}
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
int[] num_config = new int[1];
if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
num_config)) {
throw new IllegalArgumentException("eglChooseConfig failed");
}
int numConfigs = num_config[0];
if (numConfigs <= 0) {
throw new IllegalArgumentException(
"No configs match configSpec");
}
EGLConfig[] configs = new EGLConfig[numConfigs];
if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
num_config)) {
throw new IllegalArgumentException("eglChooseConfig#2 failed");
}
EGLConfig config = chooseConfig(egl, display, configs);
if (config == null) {
throw new IllegalArgumentException("No config chosen");
}
return config;
}
abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
EGLConfig[] configs);
protected int[] mConfigSpec;
private int[] filterConfigSpec(int[] configSpec) {
if (mEGLContextClientVersion != 2) {
return configSpec;
}
/* We know none of the subclasses define EGL_RENDERABLE_TYPE.
* And we know the configSpec is well formed.
*/
int len = configSpec.length;
int[] newConfigSpec = new int[len + 2];
System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
newConfigSpec[len+1] = EGL10.EGL_NONE;
return newConfigSpec;
}
}
/**
* Choose a configuration with exactly the specified r,g,b,a sizes,
* and at least the specified depth and stencil sizes.
*/
private class ComponentSizeChooser extends BaseConfigChooser {
public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
int alphaSize, int depthSize, int stencilSize) {
super(new int[] {
EGL10.EGL_RED_SIZE, redSize,
EGL10.EGL_GREEN_SIZE, greenSize,
EGL10.EGL_BLUE_SIZE, blueSize,
EGL10.EGL_ALPHA_SIZE, alphaSize,
EGL10.EGL_DEPTH_SIZE, depthSize,
EGL10.EGL_STENCIL_SIZE, stencilSize,
EGL10.EGL_NONE});
mValue = new int[1];
mRedSize = redSize;
mGreenSize = greenSize;
mBlueSize = blueSize;
mAlphaSize = alphaSize;
mDepthSize = depthSize;
mStencilSize = stencilSize;
}
@Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
EGLConfig[] configs) {
for (EGLConfig config : configs) {
int d = findConfigAttrib(egl, display, config,
EGL10.EGL_DEPTH_SIZE, 0);
int s = findConfigAttrib(egl, display, config,
EGL10.EGL_STENCIL_SIZE, 0);
if ((d >= mDepthSize) && (s >= mStencilSize)) {
int r = findConfigAttrib(egl, display, config,
EGL10.EGL_RED_SIZE, 0);
int g = findConfigAttrib(egl, display, config,
EGL10.EGL_GREEN_SIZE, 0);
int b = findConfigAttrib(egl, display, config,
EGL10.EGL_BLUE_SIZE, 0);
int a = findConfigAttrib(egl, display, config,
EGL10.EGL_ALPHA_SIZE, 0);
if ((r == mRedSize) && (g == mGreenSize)
&& (b == mBlueSize) && (a == mAlphaSize)) {
return config;
}
}
}
return null;
}
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
EGLConfig config, int attribute, int defaultValue) {
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
return mValue[0];
}
return defaultValue;
}
private int[] mValue;
// Subclasses can adjust these values:
protected int mRedSize;
protected int mGreenSize;
protected int mBlueSize;
protected int mAlphaSize;
protected int mDepthSize;
protected int mStencilSize;
}
/**
* This class will choose a RGB_888 surface with
* or without a depth buffer.
*
*/
private class SimpleEGLConfigChooser extends ComponentSizeChooser {
public SimpleEGLConfigChooser(boolean withDepthBuffer) {
super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0);
}
}
/**
* An EGL helper class.
*/
private static class EglHelper {
public EglHelper(WeakReference<GLTextureView> glTextureViewWeakRef) {
mGLTextureViewWeakRef = glTextureViewWeakRef;
}
/**
* Initialize EGL for a given configuration spec.
* @param configSpec
*/
public void start() {
if (LOG_EGL) {
Log.w("EglHelper", "start() tid=" + Thread.currentThread().getId());
}
/*
* Get an EGL instance
*/
mEgl = (EGL10) EGLContext.getEGL();
/*
* Get to the default display.
*/
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
throw new RuntimeException("eglGetDisplay failed");
}
/*
* We can now initialize EGL for that display
*/
int[] version = new int[2];
if(!mEgl.eglInitialize(mEglDisplay, version)) {
throw new RuntimeException("eglInitialize failed");
}
GLTextureView view = mGLTextureViewWeakRef.get();
if (view == null) {
mEglConfig = null;
mEglContext = null;
} else {
mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
/*
* Create an EGL context. We want to do this as rarely as we can, because an
* EGL context is a somewhat heavy object.
*/
mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
}
if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
mEglContext = null;
throwEglException("createContext");
}
if (LOG_EGL) {
Log.w("EglHelper", "createContext " + mEglContext + " tid=" + Thread.currentThread().getId());
}
mEglSurface = null;
}
/**
* Create an egl surface for the current SurfaceHolder surface. If a surface
* already exists, destroy it before creating the new surface.
*
* @return true if the surface was created successfully.
*/
public boolean createSurface() {
if (LOG_EGL) {
Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId());
}
/*
* Check preconditions.
*/
if (mEgl == null) {
throw new RuntimeException("egl not initialized");
}
if (mEglDisplay == null) {
throw new RuntimeException("eglDisplay not initialized");
}
if (mEglConfig == null) {
throw new RuntimeException("mEglConfig not initialized");
}
/*
* The window size has changed, so we need to create a new
* surface.
*/
destroySurfaceImp();
/*
* Create an EGL surface we can render into.
*/
GLTextureView view = mGLTextureViewWeakRef.get();
if (view != null) {
mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
mEglDisplay, mEglConfig, view.getSurfaceTexture());
} else {
mEglSurface = null;
}
if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
int error = mEgl.eglGetError();
if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
}
return false;
}
/*
* Before we can issue GL commands, we need to make sure
* the context is current and bound to a surface.
*/
if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
/*
* Could not make the context current, probably because the underlying
* SurfaceView surface has been destroyed.
*/
logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
return false;
}
return true;
}
/**
* Create a GL object for the current EGL context.
* @return
*/
GL createGL() {
GL gl = mEglContext.getGL();
GLTextureView view = mGLTextureViewWeakRef.get();
if (view != null) {
if (view.mGLWrapper != null) {
gl = view.mGLWrapper.wrap(gl);
}
if ((view.mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) {
int configFlags = 0;
Writer log = null;
if ((view.mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) {
configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR;
}
if ((view.mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) {
log = new LogWriter();
}
gl = GLDebugHelper.wrap(gl, configFlags, log);
}
}
return gl;
}
/**
* Display the current render surface.
* @return the EGL error code from eglSwapBuffers.
*/
public int swap() {
if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
return mEgl.eglGetError();
}
return EGL10.EGL_SUCCESS;
}
public void destroySurface() {
if (LOG_EGL) {
Log.w("EglHelper", "destroySurface() tid=" + Thread.currentThread().getId());
}
destroySurfaceImp();
}
private void destroySurfaceImp() {
if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
GLTextureView view = mGLTextureViewWeakRef.get();
if (view != null) {
view.mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
}
mEglSurface = null;
}
}
public void finish() {
if (LOG_EGL) {
Log.w("EglHelper", "finish() tid=" + Thread.currentThread().getId());
}
if (mEglContext != null) {
GLTextureView view = mGLTextureViewWeakRef.get();
if (view != null) {
view.mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext);
}
mEglContext = null;
}
if (mEglDisplay != null) {
mEgl.eglTerminate(mEglDisplay);
mEglDisplay = null;
}
}
private void throwEglException(String function) {
throwEglException(function, mEgl.eglGetError());
}
public static void throwEglException(String function, int error) {
String message = formatEglError(function, error);
if (LOG_THREADS) {
Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " "
+ message);
}
throw new RuntimeException(message);
}
public static void logEglErrorAsWarning(String tag, String function, int error) {
Log.w(tag, formatEglError(function, error));
}
public static String formatEglError(String function, int error) {
return function + " failed"; // + EGLLogWrapper.getErrorString(error);
}
private WeakReference<GLTextureView> mGLTextureViewWeakRef;
EGL10 mEgl;
EGLDisplay mEglDisplay;
EGLSurface mEglSurface;
EGLConfig mEglConfig;
EGLContext mEglContext;
}
/**
* A generic GL Thread. Takes care of initializing EGL and GL. Delegates
* to a Renderer instance to do the actual drawing. Can be configured to
* render continuously or on request.
*
* All potentially blocking synchronization is done through the
* sGLThreadManager object. This avoids multiple-lock ordering issues.
*
*/
static class GLThread extends Thread {
GLThread(WeakReference<GLTextureView> glTextureViewWeakRef) {
super();
mWidth = 0;
mHeight = 0;
mRequestRender = true;
mRenderMode = RENDERMODE_CONTINUOUSLY;
mGLTextureViewWeakRef = glTextureViewWeakRef;
}
@Override
public void run() {
setName("GLThread " + getId());
if (LOG_THREADS) {
Log.i("GLThread", "starting tid=" + getId());
}
try {
guardedRun();
} catch (InterruptedException e) {
// fall thru and exit normally
} finally {
sGLThreadManager.threadExiting(this);
}
}
/*
* This private method should only be called inside a
* synchronized(sGLThreadManager) block.
*/
private void stopEglSurfaceLocked() {
if (mHaveEglSurface) {
mHaveEglSurface = false;
mEglHelper.destroySurface();
}
}
/*
* This private method should only be called inside a
* synchronized(sGLThreadManager) block.
*/
private void stopEglContextLocked() {
if (mHaveEglContext) {
mEglHelper.finish();
mHaveEglContext = false;
sGLThreadManager.releaseEglContextLocked(this);
}
}
private void guardedRun() throws InterruptedException {
mEglHelper = new EglHelper(mGLTextureViewWeakRef);
mHaveEglContext = false;
mHaveEglSurface = false;
try {
GL10 gl = null;
boolean createEglContext = false;
boolean createEglSurface = false;
boolean createGlInterface = false;
boolean lostEglContext = false;
boolean sizeChanged = false;
boolean wantRenderNotification = false;
boolean doRenderNotification = false;
boolean askedToReleaseEglContext = false;
int w = 0;
int h = 0;
Runnable event = null;
while (true) {
synchronized (sGLThreadManager) {
while (true) {
if (mShouldExit) {
return;
}
if (! mEventQueue.isEmpty()) {
event = mEventQueue.remove(0);
break;
}
// Update the pause state.
boolean pausing = false;
if (mPaused != mRequestPaused) {
pausing = mRequestPaused;
mPaused = mRequestPaused;
sGLThreadManager.notifyAll();
if (LOG_PAUSE_RESUME) {
Log.i("GLThread", "mPaused is now " + mPaused + " tid=" + getId());
}
}
// Do we need to give up the EGL context?
if (mShouldReleaseEglContext) {
if (LOG_SURFACE) {
Log.i("GLThread", "releasing EGL context because asked to tid=" + getId());
}
stopEglSurfaceLocked();
stopEglContextLocked();
mShouldReleaseEglContext = false;
askedToReleaseEglContext = true;
}
// Have we lost the EGL context?
if (lostEglContext) {
stopEglSurfaceLocked();
stopEglContextLocked();
lostEglContext = false;
}
// When pausing, release the EGL surface:
if (pausing && mHaveEglSurface) {
if (LOG_SURFACE) {
Log.i("GLThread", "releasing EGL surface because paused tid=" + getId());
}
stopEglSurfaceLocked();
}
// When pausing, optionally release the EGL Context:
if (pausing && mHaveEglContext) {
GLTextureView view = mGLTextureViewWeakRef.get();
boolean preserveEglContextOnPause = view == null ?
false : view.mPreserveEGLContextOnPause;
if (!preserveEglContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) {
stopEglContextLocked();
if (LOG_SURFACE) {
Log.i("GLThread", "releasing EGL context because paused tid=" + getId());
}
}
}
// When pausing, optionally terminate EGL:
if (pausing) {
if (sGLThreadManager.shouldTerminateEGLWhenPausing()) {
mEglHelper.finish();
if (LOG_SURFACE) {
Log.i("GLThread", "terminating EGL because paused tid=" + getId());
}
}
}
// Have we lost the SurfaceView surface?
if ((! mHasSurface) && (! mWaitingForSurface)) {
if (LOG_SURFACE) {
Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId());
}
if (mHaveEglSurface) {
stopEglSurfaceLocked();
}
mWaitingForSurface = true;
mSurfaceIsBad = false;
sGLThreadManager.notifyAll();
}
// Have we acquired the surface view surface?
if (mHasSurface && mWaitingForSurface) {
if (LOG_SURFACE) {
Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId());
}
mWaitingForSurface = false;
sGLThreadManager.notifyAll();
}
if (doRenderNotification) {
if (LOG_SURFACE) {
Log.i("GLThread", "sending render notification tid=" + getId());
}
wantRenderNotification = false;
doRenderNotification = false;
mRenderComplete = true;
sGLThreadManager.notifyAll();
}
// Ready to draw?
if (readyToDraw()) {
// If we don't have an EGL context, try to acquire one.
if (! mHaveEglContext) {
if (askedToReleaseEglContext) {
askedToReleaseEglContext = false;
} else if (sGLThreadManager.tryAcquireEglContextLocked(this)) {
try {
mEglHelper.start();
} catch (RuntimeException t) {
sGLThreadManager.releaseEglContextLocked(this);
throw t;
}
mHaveEglContext = true;
createEglContext = true;
sGLThreadManager.notifyAll();
}
}
if (mHaveEglContext && !mHaveEglSurface) {
mHaveEglSurface = true;
createEglSurface = true;
createGlInterface = true;
sizeChanged = true;
}
if (mHaveEglSurface) {
if (mSizeChanged) {
sizeChanged = true;
w = mWidth;
h = mHeight;
wantRenderNotification = true;
if (LOG_SURFACE) {
Log.i("GLThread",
"noticing that we want render notification tid="
+ getId());
}
// Destroy and recreate the EGL surface.
createEglSurface = true;
mSizeChanged = false;
}
mRequestRender = false;
sGLThreadManager.notifyAll();
break;
}
}
// By design, this is the only place in a GLThread thread where we wait().
if (LOG_THREADS) {
Log.i("GLThread", "waiting tid=" + getId()
+ " mHaveEglContext: " + mHaveEglContext
+ " mHaveEglSurface: " + mHaveEglSurface
+ " mFinishedCreatingEglSurface: " + mFinishedCreatingEglSurface
+ " mPaused: " + mPaused
+ " mHasSurface: " + mHasSurface
+ " mSurfaceIsBad: " + mSurfaceIsBad
+ " mWaitingForSurface: " + mWaitingForSurface
+ " mWidth: " + mWidth
+ " mHeight: " + mHeight
+ " mRequestRender: " + mRequestRender
+ " mRenderMode: " + mRenderMode);
}
sGLThreadManager.wait();
}
} // end of synchronized(sGLThreadManager)
if (event != null) {
event.run();
event = null;
continue;
}
if (createEglSurface) {
if (LOG_SURFACE) {
Log.w("GLThread", "egl createSurface");
}
if (mEglHelper.createSurface()) {
synchronized(sGLThreadManager) {
mFinishedCreatingEglSurface = true;
sGLThreadManager.notifyAll();
}
} else {
synchronized(sGLThreadManager) {
mFinishedCreatingEglSurface = true;
mSurfaceIsBad = true;
sGLThreadManager.notifyAll();
}
continue;
}
createEglSurface = false;
}
if (createGlInterface) {
gl = (GL10) mEglHelper.createGL();
sGLThreadManager.checkGLDriver(gl);
createGlInterface = false;
}
if (createEglContext) {
if (LOG_RENDERER) {
Log.w("GLThread", "onSurfaceCreated");
}
GLTextureView view = mGLTextureViewWeakRef.get();
if (view != null) {
view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
}
createEglContext = false;
}
if (sizeChanged) {
if (LOG_RENDERER) {
Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")");
}
GLTextureView view = mGLTextureViewWeakRef.get();
if (view != null) {
view.mRenderer.onSurfaceChanged(gl, w, h);
}
sizeChanged = false;
}
if (LOG_RENDERER_DRAW_FRAME) {
Log.w("GLThread", "onDrawFrame tid=" + getId());
}
{
GLTextureView view = mGLTextureViewWeakRef.get();
if (view != null) {
view.mRenderer.onDrawFrame(gl);
}
}
int swapError = mEglHelper.swap();
switch (swapError) {
case EGL10.EGL_SUCCESS:
break;
case EGL11.EGL_CONTEXT_LOST:
if (LOG_SURFACE) {
Log.i("GLThread", "egl context lost tid=" + getId());
}
lostEglContext = true;
break;
default:
// Other errors typically mean that the current surface is bad,
// probably because the SurfaceView surface has been destroyed,
// but we haven't been notified yet.
// Log the error to help developers understand why rendering stopped.
EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError);
synchronized(sGLThreadManager) {
mSurfaceIsBad = true;
sGLThreadManager.notifyAll();
}
break;
}
if (wantRenderNotification) {
doRenderNotification = true;
}
}
} finally {
/*
* clean-up everything...
*/
synchronized (sGLThreadManager) {
stopEglSurfaceLocked();
stopEglContextLocked();
}
}
}
public boolean ableToDraw() {
return mHaveEglContext && mHaveEglSurface && readyToDraw();
}
private boolean readyToDraw() {
return (!mPaused) && mHasSurface && (!mSurfaceIsBad)
&& (mWidth > 0) && (mHeight > 0)
&& (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY));
}
public void setRenderMode(int renderMode) {
if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) {
throw new IllegalArgumentException("renderMode");
}
synchronized(sGLThreadManager) {
mRenderMode = renderMode;
sGLThreadManager.notifyAll();
}
}
public int getRenderMode() {
synchronized(sGLThreadManager) {
return mRenderMode;
}
}
public void requestRender() {
synchronized(sGLThreadManager) {
mRequestRender = true;
sGLThreadManager.notifyAll();
}
}
public void surfaceCreated() {
synchronized(sGLThreadManager) {
if (LOG_THREADS) {
Log.i("GLThread", "surfaceCreated tid=" + getId());
}
mHasSurface = true;
mFinishedCreatingEglSurface = false;
sGLThreadManager.notifyAll();
while (mWaitingForSurface
&& !mFinishedCreatingEglSurface
&& !mExited) {
try {
sGLThreadManager.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
public void surfaceDestroyed() {
synchronized(sGLThreadManager) {
if (LOG_THREADS) {
Log.i("GLThread", "surfaceDestroyed tid=" + getId());
}
mHasSurface = false;
sGLThreadManager.notifyAll();
while((!mWaitingForSurface) && (!mExited)) {
try {
sGLThreadManager.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
public void onPause() {
synchronized (sGLThreadManager) {
if (LOG_PAUSE_RESUME) {
Log.i("GLThread", "onPause tid=" + getId());
}
mRequestPaused = true;
sGLThreadManager.notifyAll();
while ((! mExited) && (! mPaused)) {
if (LOG_PAUSE_RESUME) {
Log.i("Main thread", "onPause waiting for mPaused.");
}
try {
sGLThreadManager.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
public void onResume() {
synchronized (sGLThreadManager) {
if (LOG_PAUSE_RESUME) {
Log.i("GLThread", "onResume tid=" + getId());
}
mRequestPaused = false;
mRequestRender = true;
mRenderComplete = false;
sGLThreadManager.notifyAll();
while ((! mExited) && mPaused && (!mRenderComplete)) {
if (LOG_PAUSE_RESUME) {
Log.i("Main thread", "onResume waiting for !mPaused.");
}
try {
sGLThreadManager.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
public void onWindowResize(int w, int h) {
synchronized (sGLThreadManager) {
mWidth = w;
mHeight = h;
mSizeChanged = true;
mRequestRender = true;
mRenderComplete = false;
sGLThreadManager.notifyAll();
// Wait for thread to react to resize and render a frame
while (! mExited && !mPaused && !mRenderComplete
&& ableToDraw()) {
if (LOG_SURFACE) {
Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + getId());
}
try {
sGLThreadManager.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
public void requestExitAndWait() {
// don't call this from GLThread thread or it is a guaranteed
// deadlock!
synchronized(sGLThreadManager) {
mShouldExit = true;
sGLThreadManager.notifyAll();
while (! mExited) {
try {
sGLThreadManager.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
public void requestReleaseEglContextLocked() {
mShouldReleaseEglContext = true;
sGLThreadManager.notifyAll();
}
/**
* Queue an "event" to be run on the GL rendering thread.
* @param r the runnable to be run on the GL rendering thread.
*/
public void queueEvent(Runnable r) {
if (r == null) {
throw new IllegalArgumentException("r must not be null");
}
synchronized(sGLThreadManager) {
mEventQueue.add(r);
sGLThreadManager.notifyAll();
}
}
// Once the thread is started, all accesses to the following member
// variables are protected by the sGLThreadManager monitor
private boolean mShouldExit;
private boolean mExited;
private boolean mRequestPaused;
private boolean mPaused;
private boolean mHasSurface;
private boolean mSurfaceIsBad;
private boolean mWaitingForSurface;
private boolean mHaveEglContext;
private boolean mHaveEglSurface;
private boolean mFinishedCreatingEglSurface;
private boolean mShouldReleaseEglContext;
private int mWidth;
private int mHeight;
private int mRenderMode;
private boolean mRequestRender;
private boolean mRenderComplete;
private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
private boolean mSizeChanged = true;
// End of member variables protected by the sGLThreadManager monitor.
private EglHelper mEglHelper;
/**
* Set once at thread construction time, nulled out when the parent view is garbage
* called. This weak reference allows the GLSurfaceView to be garbage collected while
* the GLThread is still alive.
*/
private WeakReference<GLTextureView> mGLTextureViewWeakRef;
}
static class LogWriter extends Writer {
@Override public void close() {
flushBuilder();
}
@Override public void flush() {
flushBuilder();
}
@Override public void write(char[] buf, int offset, int count) {
for(int i = 0; i < count; i++) {
char c = buf[offset + i];
if ( c == '\n') {
flushBuilder();
}
else {
mBuilder.append(c);
}
}
}
private void flushBuilder() {
if (mBuilder.length() > 0) {
Log.v("GLSurfaceView", mBuilder.toString());
mBuilder.delete(0, mBuilder.length());
}
}
private StringBuilder mBuilder = new StringBuilder();
}
private void checkRenderThreadState() {
if (mGLThread != null) {
throw new IllegalStateException(
"setRenderer has already been called for this instance.");
}
}
private static class GLThreadManager {
private static String TAG = "GLThreadManager";
public synchronized void threadExiting(GLThread thread) {
if (LOG_THREADS) {
Log.i("GLThread", "exiting tid=" + thread.getId());
}
thread.mExited = true;
if (mEglOwner == thread) {
mEglOwner = null;
}
notifyAll();
}
/*
* Tries once to acquire the right to use an EGL
* context. Does not block. Requires that we are already
* in the sGLThreadManager monitor when this is called.
*
* @return true if the right to use an EGL context was acquired.
*/
public boolean tryAcquireEglContextLocked(GLThread thread) {
if (mEglOwner == thread || mEglOwner == null) {
mEglOwner = thread;
notifyAll();
return true;
}
checkGLESVersion();
if (mMultipleGLESContextsAllowed) {
return true;
}
// Notify the owning thread that it should release the context.
// TODO: implement a fairness policy. Currently
// if the owning thread is drawing continuously it will just
// reacquire the EGL context.
if (mEglOwner != null) {
mEglOwner.requestReleaseEglContextLocked();
}
return false;
}
/*
* Releases the EGL context. Requires that we are already in the
* sGLThreadManager monitor when this is called.
*/
public void releaseEglContextLocked(GLThread thread) {
if (mEglOwner == thread) {
mEglOwner = null;
}
notifyAll();
}
public synchronized boolean shouldReleaseEGLContextWhenPausing() {
// Release the EGL context when pausing even if
// the hardware supports multiple EGL contexts.
// Otherwise the device could run out of EGL contexts.
return mLimitedGLESContexts;
}
public synchronized boolean shouldTerminateEGLWhenPausing() {
checkGLESVersion();
return !mMultipleGLESContextsAllowed;
}
public synchronized void checkGLDriver(GL10 gl) {
if (! mGLESDriverCheckComplete) {
checkGLESVersion();
String renderer = gl.glGetString(GL10.GL_RENDERER);
if (mGLESVersion < kGLES_20) {
mMultipleGLESContextsAllowed =
! renderer.startsWith(kMSM7K_RENDERER_PREFIX);
notifyAll();
}
mLimitedGLESContexts = !mMultipleGLESContextsAllowed;
if (LOG_SURFACE) {
Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = "
+ mMultipleGLESContextsAllowed
+ " mLimitedGLESContexts = " + mLimitedGLESContexts);
}
mGLESDriverCheckComplete = true;
}
}
private void checkGLESVersion() {
if (! mGLESVersionCheckComplete) {
// mGLESVersion = SystemProperties.getInt(
// "ro.opengles.version",
// ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
// if (mGLESVersion >= kGLES_20) {
mMultipleGLESContextsAllowed = true;
// }
if (LOG_SURFACE) {
Log.w(TAG, "checkGLESVersion mGLESVersion =" +
" " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed);
}
mGLESVersionCheckComplete = true;
}
}
/**
* This check was required for some pre-Android-3.0 hardware. Android 3.0 provides
* support for hardware-accelerated views, therefore multiple EGL contexts are
* supported on all Android 3.0+ EGL drivers.
*/
private boolean mGLESVersionCheckComplete;
private int mGLESVersion;
private boolean mGLESDriverCheckComplete;
private boolean mMultipleGLESContextsAllowed;
private boolean mLimitedGLESContexts;
private static final int kGLES_20 = 0x20000;
private static final String kMSM7K_RENDERER_PREFIX =
"Q3Dimension MSM7500 ";
private GLThread mEglOwner;
}
private static final GLThreadManager sGLThreadManager = new GLThreadManager();
private final WeakReference<GLTextureView> mThisWeakRef =
new WeakReference<GLTextureView>(this);
private GLThread mGLThread;
private GLSurfaceView.Renderer mRenderer;
private boolean mDetached;
private EGLConfigChooser mEGLConfigChooser;
private EGLContextFactory mEGLContextFactory;
private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;
private GLWrapper mGLWrapper;
private int mDebugFlags;
private int mEGLContextClientVersion;
private boolean mPreserveEGLContextOnPause;
}
================================================
FILE: library/src/main/java/com/roger/missview/library/GLUtil.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library;
import android.graphics.Bitmap;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class GLUtil {
public static final int BYTES_PER_FLOAT = 4;
public static int loadShader(int type, String shaderCode) {
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shaderHandle = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shaderHandle, shaderCode);
GLES20.glCompileShader(shaderHandle);
checkGlError("glCompileShader");
return shaderHandle;
}
public static int createAndLinkProgram(int vertexShaderHandle, int fragShaderHandle,
String[] attributes) {
int programHandle = GLES20.glCreateProgram();
GLUtil.checkGlError("glCreateProgram");
GLES20.glAttachShader(programHandle, vertexShaderHandle);
GLES20.glAttachShader(programHandle, fragShaderHandle);
if (attributes != null) {
final int size = attributes.length;
for (int i = 0; i < size; i++) {
GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
}
}
GLES20.glLinkProgram(programHandle);
GLUtil.checkGlError("glLinkProgram");
GLES20.glDeleteShader(vertexShaderHandle);
GLES20.glDeleteShader(fragShaderHandle);
return programHandle;
}
public static int loadTexture(Bitmap bitmap) {
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
GLUtil.checkGlError("glGenTextures");
if (textureHandle[0] != 0) {
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
GLUtil.checkGlError("texImage2D");
}
if (textureHandle[0] == 0) {
}
return textureHandle[0];
}
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
}
}
public static FloatBuffer asFloatBuffer(float[] array) {
FloatBuffer buffer = newFloatBuffer(array.length);
buffer.put(array);
buffer.position(0);
return buffer;
}
public static FloatBuffer newFloatBuffer(int size) {
FloatBuffer buffer = ByteBuffer.allocateDirect(size * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
buffer.position(0);
return buffer;
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/MissView.java
================================================
package com.roger.missview.library;
import android.content.Context;
import android.graphics.Bitmap;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
/**
* Created by Administrator on 2015/4/30.
*/
public class MissView extends GLTextureView
implements RenderController.Callbacks, BlurRenderer.Callbacks {
private BlurRenderer mRenderer;
private RenderController mRenderController;
public MissView(Context context) {
super(context);
init();
}
public MissView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mRenderer = new BlurRenderer(getContext(), this);
setEGLContextClientVersion(2);
setEGLConfigChooser(8, 8, 8, 8, 0, 0);
setRenderer(mRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
public void initPicture(String mPictureName) {
mRenderController = new DemoRenderController(getContext(), mRenderer, this, true, mPictureName);
mRenderer.setDemoMode(true);
mRenderController.setVisible(true);
}
public void initPicture(Bitmap mBitmap) {
mRenderController = new DemoRenderController(getContext(), mRenderer, this, true, mBitmap);
mRenderer.setDemoMode(true);
mRenderController.setVisible(true);
}
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mRenderer.hintViewportSize(w, h);
mRenderController.reloadCurrentArtwork(true);
}
@Override protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (null != mRenderController) {
mRenderController.destroy();
queueEventOnGlThread(new Runnable() {
@Override public void run() {
mRenderer.destroy();
}
});
}
}
@Override public void queueEventOnGlThread(Runnable runnable) {
if (this == null) {
return;
}
super.queueEvent(runnable);
}
@Override public void requestRender() {
if (this == null) {
return;
}
super.requestRender();
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/RenderController.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library;
import android.content.Context;
import android.os.AsyncTask;
import com.roger.missview.library.util.BitmapRegionLoader;
public abstract class RenderController {
protected Context mContext;
protected BlurRenderer mRenderer;
protected Callbacks mCallbacks;
protected boolean mVisible;
private BitmapRegionLoader mQueuedBitmapRegionLoader;
public RenderController(Context context, BlurRenderer renderer, Callbacks callbacks) {
mRenderer = renderer;
mContext = context;
mCallbacks = callbacks;
}
public void destroy() {
if (mQueuedBitmapRegionLoader != null) {
mQueuedBitmapRegionLoader.destroy();
}
}
protected abstract BitmapRegionLoader openDownloadedCurrentArtwork(boolean forceReload);
public void reloadCurrentArtwork(final boolean forceReload) {
new AsyncTask<Void, Void, BitmapRegionLoader>() {
@Override
protected BitmapRegionLoader doInBackground(Void... voids) {
// openDownloadedCurrentArtwork should be called on a background thread
return openDownloadedCurrentArtwork(forceReload);
}
@Override
protected void onPostExecute(final BitmapRegionLoader bitmapRegionLoader) {
if (bitmapRegionLoader == null) {
return;
}
mCallbacks.queueEventOnGlThread(new Runnable() {
@Override
public void run() {
if (mVisible) {
mRenderer.setAndConsumeBitmapRegionLoader(bitmapRegionLoader);
} else {
mQueuedBitmapRegionLoader = bitmapRegionLoader;
}
}
});
}
}.execute((Void) null);
}
public void setVisible(boolean visible) {
mVisible = visible;
if (visible) {
mCallbacks.queueEventOnGlThread(new Runnable() {
@Override
public void run() {
if (mQueuedBitmapRegionLoader != null) {
mRenderer.setAndConsumeBitmapRegionLoader(mQueuedBitmapRegionLoader);
mQueuedBitmapRegionLoader = null;
}
}
});
mCallbacks.requestRender();
}
}
public static interface Callbacks {
void queueEventOnGlThread(Runnable runnable);
void requestRender();
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/util/ArtDetailViewport.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library.util;
import android.graphics.RectF;
// Singleton that also behaves as an event
public class ArtDetailViewport {
private volatile RectF mViewport0 = new RectF();
private volatile RectF mViewport1 = new RectF();
private boolean mFromUser;
private static ArtDetailViewport sInstance = new ArtDetailViewport();
public static ArtDetailViewport getInstance() {
return sInstance;
}
private ArtDetailViewport() {
}
public RectF getViewport(int id) {
return (id == 0) ? mViewport0 : mViewport1;
}
public ArtDetailViewport setViewport(int id, RectF viewport, boolean fromUser) {
return setViewport(id, viewport.left, viewport.top, viewport.right, viewport.bottom,
fromUser);
}
public ArtDetailViewport setViewport(int id, float left, float top, float right, float bottom,
boolean fromUser) {
mFromUser = fromUser;
getViewport(id).set(left, top, right, bottom);
return this;
}
public boolean isFromUser() {
return mFromUser;
}
public ArtDetailViewport setDefaultViewport(int id, float bitmapAspectRatio,
float screenAspectRatio) {
mFromUser = false;
if (bitmapAspectRatio > screenAspectRatio) {
getViewport(id).set(
0.5f - screenAspectRatio / bitmapAspectRatio / 2,
0,
0.5f + screenAspectRatio / bitmapAspectRatio / 2,
1);
} else {
getViewport(id).set(
0,
0.5f - bitmapAspectRatio / screenAspectRatio / 2,
1,
0.5f + bitmapAspectRatio / screenAspectRatio / 2);
}
return this;
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/util/BitmapRegionLoader.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library.util;
import android.graphics.Bitmap;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import static android.graphics.BitmapFactory.Options;
/**
* Wrapper for {@link android.graphics.BitmapRegionDecoder} with some extra functionality.
*/
public class BitmapRegionLoader {
private boolean mValid = false;
private int mRotation = 0;
private int mOriginalWidth;
private int mOriginalHeight;
private Rect mTempRect = new Rect();
private InputStream mInputStream;
private volatile BitmapRegionDecoder mBitmapRegionDecoder;
private Matrix mRotateMatrix;
public static BitmapRegionLoader newInstance(InputStream in) {
return newInstance(in, 0);
}
public static BitmapRegionLoader newInstance(InputStream in, int rotation) {
if (in == null) {
Log.e("BitmapRegionLoader", "InputStream is null!");
return null;
}
BitmapRegionLoader loader = new BitmapRegionLoader(in);
if (loader.mValid) {
loader.mRotation = rotation;
if (loader.mRotation != 0) {
loader.mRotateMatrix = new Matrix();
loader.mRotateMatrix.postRotate(rotation);
}
return loader;
}
return null;
}
private BitmapRegionLoader(InputStream in) {
mInputStream = in;
try {
mBitmapRegionDecoder = BitmapRegionDecoder.newInstance(in, false);
mOriginalWidth = mBitmapRegionDecoder.getWidth();
mOriginalHeight = mBitmapRegionDecoder.getHeight();
mValid = true;
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Key difference, aside from support for ration, from
* {@link android.graphics.BitmapRegionDecoder#decodeRegion(android.graphics.Rect, android.graphics.BitmapFactory.Options)} in this implementation is that even
* if <code>inBitmap</code> is given, a sub-bitmap might be returned.
*/
public synchronized Bitmap decodeRegion(Rect rect, Options options) {
int unsampledInBitmapWidth = -1;
int unsampledInBitmapHeight = -1;
int sampleSize = Math.max(1, options != null ? options.inSampleSize : 1);
if (options != null && options.inBitmap != null) {
unsampledInBitmapWidth = options.inBitmap.getWidth() * sampleSize;
unsampledInBitmapHeight = options.inBitmap.getHeight() * sampleSize;
}
// Decode with rotation
switch (mRotation) {
case 90:
mTempRect.set(
rect.top, mOriginalHeight - rect.right,
rect.bottom, mOriginalHeight - rect.left);
break;
case 180:
mTempRect.set(
mOriginalWidth - rect.right, mOriginalHeight - rect.bottom,
mOriginalWidth - rect.left, mOriginalHeight - rect.top);
break;
case 270:
mTempRect.set(
mOriginalWidth - rect.bottom, rect.left,
mOriginalWidth - rect.top, rect.right);
break;
default:
mTempRect.set(rect);
}
Bitmap bitmap = mBitmapRegionDecoder.decodeRegion(mTempRect, options);
if (options != null && options.inBitmap != null &&
((mTempRect.width() != unsampledInBitmapWidth
|| mTempRect.height() != unsampledInBitmapHeight))) {
// Need to extract the sub-bitmap
Bitmap subBitmap = Bitmap.createBitmap(
bitmap, 0, 0,
mTempRect.width() / sampleSize,
mTempRect.height() / sampleSize);
if (bitmap != options.inBitmap) {
bitmap.recycle();
}
bitmap = subBitmap;
}
if (mRotateMatrix != null) {
// Rotate decoded bitmap
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(),
mRotateMatrix, true);
if (options == null || bitmap != options.inBitmap) {
bitmap.recycle();
}
bitmap = rotatedBitmap;
}
return bitmap;
}
public synchronized int getWidth() {
return (mRotation == 90 || mRotation == 270) ? mOriginalHeight : mOriginalWidth;
}
public synchronized int getHeight() {
return (mRotation == 90 || mRotation == 270) ? mOriginalWidth : mOriginalHeight;
}
public synchronized void destroy() {
mBitmapRegionDecoder.recycle();
mBitmapRegionDecoder = null;
try {
mInputStream.close();
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/util/ImageBlurrer.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.Matrix3f;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.renderscript.ScriptIntrinsicColorMatrix;
public class ImageBlurrer {
public static final int MAX_SUPPORTED_BLUR_PIXELS = 25;
private RenderScript mRS;
private ScriptIntrinsicBlur mSIBlur;
private ScriptIntrinsicColorMatrix mSIGrey;
private Allocation mTmp1;
private Allocation mTmp2;
public ImageBlurrer(Context context) {
mRS = RenderScript.create(context);
mSIBlur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
mSIGrey = ScriptIntrinsicColorMatrix.create(mRS);
}
public Bitmap blurBitmap(Bitmap src, float radius, float desaturateAmount) {
Bitmap dest = Bitmap.createBitmap(src);
if ((int) radius == 0) {
return dest;
}
if (mTmp1 != null) {
mTmp1.destroy();
}
if (mTmp2 != null) {
mTmp2.destroy();
}
mTmp1 = Allocation.createFromBitmap(mRS, src);
mTmp2 = Allocation.createFromBitmap(mRS, dest);
mSIBlur.setRadius((int) radius);
mSIBlur.setInput(mTmp1);
mSIBlur.forEach(mTmp2);
if (desaturateAmount > 0) {
desaturateAmount = MathUtil.constrain(0, 1, desaturateAmount);
Matrix3f m = new Matrix3f(new float[]{
MathUtil.interpolate(1, 0.299f, desaturateAmount),
MathUtil.interpolate(0, 0.299f, desaturateAmount),
MathUtil.interpolate(0, 0.299f, desaturateAmount),
MathUtil.interpolate(0, 0.587f, desaturateAmount),
MathUtil.interpolate(1, 0.587f, desaturateAmount),
MathUtil.interpolate(0, 0.587f, desaturateAmount),
MathUtil.interpolate(0, 0.114f, desaturateAmount),
MathUtil.interpolate(0, 0.114f, desaturateAmount),
MathUtil.interpolate(1, 0.114f, desaturateAmount),
});
mSIGrey.setColorMatrix(m);
mSIGrey.forEach(mTmp2, mTmp1);
mTmp1.copyTo(dest);
} else {
mTmp2.copyTo(dest);
}
return dest;
}
public void destroy() {
mSIBlur.destroy();
if (mTmp1 != null) {
mTmp1.destroy();
}
if (mTmp2 != null) {
mTmp2.destroy();
}
mRS.destroy();
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/util/ImageUtil.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library.util;
import android.graphics.Bitmap;
import android.graphics.Color;
public class ImageUtil {
// Make sure input images are very small!
public static float calculateDarkness(Bitmap bitmap) {
if (bitmap == null) {
return 0;
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int totalLum = 0;
int n = 0;
int x, y, color;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
++n;
color = bitmap.getPixel(x, y);
totalLum += (0.21f * Color.red(color)
+ 0.71f * Color.green(color)
+ 0.07f * Color.blue(color));
}
}
return (totalLum / n) / 256f;
}
private ImageUtil() {
}
public static int calculateSampleSize(int rawHeight, int targetHeight) {
int sampleSize = 1;
while (rawHeight / (sampleSize << 1) > targetHeight) {
sampleSize <<= 1;
}
return sampleSize;
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/util/MathUtil.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library.util;
import android.util.FloatMath;
public class MathUtil {
public static float constrain(float min, float max, float v) {
return Math.max(min, Math.min(max, v));
}
public static float interpolate(float x1, float x2, float f) {
return x1 + (x2 - x1) * f;
}
public static float uninterpolate(float x1, float x2, float v) {
if (x2 - x1 == 0) {
throw new IllegalArgumentException("Can't reverse interpolate with domain size of 0");
}
return (v - x1) / (x2 - x1);
}
public static float dist(float x, float y) {
return FloatMath.sqrt(x * x + y * y);
}
public static int floorEven(int num) {
return num & ~0x01;
}
public static int roundMult4(int num) {
return (num + 2) & ~0x03;
}
public static boolean isEven(int num) {
return num % 2 == 0;
}
private MathUtil() {
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/util/TickingFloatAnimator.java
================================================
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.roger.missview.library.util;
import android.animation.TimeInterpolator;
import android.os.SystemClock;
import android.view.animation.AccelerateDecelerateInterpolator;
// Non thread-safe
public class TickingFloatAnimator {
private float mStartValue = 0;
private float mCurrentValue;
private float mEndValue;
private boolean mRunning = false;
private long mStartTime;
private int mDuration = 1000;
private Runnable mEndCallback;
private TimeInterpolator mInterpolator = new AccelerateDecelerateInterpolator();
public static TickingFloatAnimator create() {
return new TickingFloatAnimator();
}
public TickingFloatAnimator from(float startValue) {
cancel();
mStartValue = startValue;
mCurrentValue = startValue;
return this;
}
public TickingFloatAnimator to(float endValue) {
mEndValue = endValue;
return this;
}
public TickingFloatAnimator withDuration(int duration) {
mDuration = Math.max(0, duration);
return this;
}
public TickingFloatAnimator withInterpolator(TimeInterpolator interpolator) {
mInterpolator = interpolator;
return this;
}
public TickingFloatAnimator withEndListener(Runnable listener) {
mEndCallback = listener;
return this;
}
public void cancel() {
mRunning = false;
mEndValue = mCurrentValue;
}
public boolean tick() {
if (!mRunning) {
return false;
}
float t;
if (mDuration <= 0) {
t = 1;
} else {
t = (float) (SystemClock.elapsedRealtime() - mStartTime) * 1f / mDuration;
if (t >= 1) {
t = 1;
}
}
if (t >= 1) {
// Ended
mRunning = false;
mCurrentValue = mEndValue;
if (mEndCallback != null) {
mEndCallback.run();
}
return false;
}
// Still running; compute value
mCurrentValue = mStartValue + mInterpolator.getInterpolation(t) * (mEndValue - mStartValue);
mRunning = true;
return true;
}
public void start() {
mRunning = true;
mStartValue = mCurrentValue;
mStartTime = SystemClock.elapsedRealtime();
tick();
}
public boolean isRunning() {
return mRunning;
}
public float currentValue() {
return mCurrentValue;
}
private TickingFloatAnimator() {
}
}
================================================
FILE: library/src/main/java/com/roger/missview/library/util/UriUtil.java
================================================
package com.roger.missview.library.util;
import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
/**
* Created by Administrator on 2015/4/28.
*/
public class UriUtil {
/**
* 根据Uri获取图片绝对路径,解决Android4.4以上版本Uri转换
* @param context
* @param imageUri
*/
@TargetApi(19)
public static String getImageAbsolutePath(Context context, Uri imageUri) {
if (context == null || imageUri == null)
return null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, imageUri)) {
if (isExternalStorageDocument(imageUri)) {
String docId = DocumentsContract.getDocumentId(imageUri);
String[] split = docId.split(":");
String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else if (isDownloadsDocument(imageUri)) {
String id = DocumentsContract.getDocumentId(imageUri);
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
} else if (isMediaDocument(imageUri)) {
String docId = DocumentsContract.getDocumentId(imageUri);
String[] split = docId.split(":");
String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
String selection = MediaStore.Images.Media._ID + "=?";
String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection, selectionArgs);
}
} // MediaStore (and general)
else if ("content".equalsIgnoreCase(imageUri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(imageUri))
return imageUri.getLastPathSegment();
return getDataColumn(context, imageUri, null, null);
}
// File
else if ("file".equalsIgnoreCase(imageUri.getScheme())) {
return imageUri.getPath();
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
String column = MediaStore.Images.Media.DATA;
String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
}
================================================
FILE: settings.gradle
================================================
include ':library', ':demo'
gitextract_d2mizj6n/ ├── .gitignore ├── .idea/ │ ├── .name │ ├── compiler.xml │ ├── copyright/ │ │ └── profiles_settings.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── MissView.iml ├── README.md ├── build.gradle ├── demo/ │ ├── .gitignore │ ├── build.gradle │ ├── demo.iml │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── roger/ │ │ └── missview/ │ │ └── ApplicationTest.java │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── roger/ │ │ └── missview/ │ │ └── MainActivity.java │ └── res/ │ ├── layout/ │ │ └── activity_main.xml │ ├── menu/ │ │ └── menu_main.xml │ ├── values/ │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── values-w820dp/ │ └── dimens.xml ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── library/ │ ├── .gitignore │ ├── build.gradle │ ├── library.iml │ ├── libs/ │ │ └── picasso-2.1.1.jar │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── roger/ │ │ └── missview/ │ │ └── library/ │ │ └── ApplicationTest.java │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── com/ │ └── roger/ │ └── missview/ │ └── library/ │ ├── BlurRenderer.java │ ├── DemoRenderController.java │ ├── GLColorOverlay.java │ ├── GLPicture.java │ ├── GLTextureView.java │ ├── GLUtil.java │ ├── MissView.java │ ├── RenderController.java │ └── util/ │ ├── ArtDetailViewport.java │ ├── BitmapRegionLoader.java │ ├── ImageBlurrer.java │ ├── ImageUtil.java │ ├── MathUtil.java │ ├── TickingFloatAnimator.java │ └── UriUtil.java └── settings.gradle
SYMBOL INDEX (238 symbols across 18 files)
FILE: demo/src/androidTest/java/com/roger/missview/ApplicationTest.java
class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
method ApplicationTest (line 10) | public ApplicationTest() {
FILE: demo/src/main/java/com/roger/missview/MainActivity.java
class MainActivity (line 18) | public class MainActivity extends Activity {
method onCreate (line 23) | @Override
method initImage (line 33) | private void initImage() {
method assetsDataToSD (line 46) | private void assetsDataToSD(String fileName) throws IOException {
method getSDPath (line 61) | public String getSDPath() {
FILE: library/src/androidTest/java/com/roger/missview/library/ApplicationTest.java
class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
method ApplicationTest (line 10) | public ApplicationTest() {
FILE: library/src/main/java/com/roger/missview/library/BlurRenderer.java
class BlurRenderer (line 46) | public class BlurRenderer implements GLSurfaceView.Renderer {
method BlurRenderer (line 93) | public BlurRenderer(Context context, Callbacks callbacks) {
method getNumberOfKeyframes (line 108) | @TargetApi(Build.VERSION_CODES.KITKAT)
method recomputeMaxPrescaledBlurPixels (line 121) | public void recomputeMaxPrescaledBlurPixels() {
method recomputeMaxDimAmount (line 135) | public void recomputeMaxDimAmount() {
method recomputeGreyAmount (line 140) | public void recomputeGreyAmount() {
method onSurfaceCreated (line 145) | public void onSurfaceCreated(GL10 unused, EGLConfig config) {
method onSurfaceChanged (line 172) | public void onSurfaceChanged(GL10 unused, int width, int height) {
method hintViewportSize (line 185) | public void hintViewportSize(int width, int height) {
method onDrawFrame (line 190) | public void onDrawFrame(GL10 unused) {
method setNormalOffsetX (line 220) | public void setNormalOffsetX(float x) {
method onViewportChanged (line 225) | private void onViewportChanged() {
method blurRadiusAtFrame (line 233) | private float blurRadiusAtFrame(float f) {
method setAndConsumeBitmapRegionLoader (line 237) | public void setAndConsumeBitmapRegionLoader(final BitmapRegionLoader b...
method setDemoMode (line 279) | public void setDemoMode(boolean demoMode) {
method setIsPreview (line 282) | public void setIsPreview(boolean preview) {
class GLPictureSet (line 286) | private class GLPictureSet {
method GLPictureSet (line 295) | public GLPictureSet(int id) {
method load (line 299) | public void load(BitmapRegionLoader bitmapRegionLoader) {
method recomputeTransformMatrices (line 374) | private void recomputeTransformMatrices() {
method drawFrame (line 432) | public void drawFrame(float globalAlpha) {
method destroyPictures (line 470) | public void destroyPictures() {
method destroy (line 482) | public void destroy() {
method isBlurred (line 487) | public boolean isBlurred() {
method setIsBlurred (line 491) | public void setIsBlurred(final boolean isBlurred, final boolean artDet...
type Callbacks (line 516) | public static interface Callbacks {
method requestRender (line 517) | void requestRender();
FILE: library/src/main/java/com/roger/missview/library/DemoRenderController.java
class DemoRenderController (line 32) | public class DemoRenderController extends RenderController {
method DemoRenderController (line 46) | public DemoRenderController(Context context, BlurRenderer renderer, Ca...
method DemoRenderController (line 54) | public DemoRenderController(Context context, BlurRenderer renderer, Ca...
method runAnimation (line 62) | private void runAnimation() {
method destroy (line 92) | @Override public void destroy() {
method openDownloadedCurrentArtwork (line 100) | @Override protected BitmapRegionLoader openDownloadedCurrentArtwork(bo...
method Bitmap2IS (line 115) | private InputStream Bitmap2IS(Bitmap bm) {
FILE: library/src/main/java/com/roger/missview/library/GLColorOverlay.java
class GLColorOverlay (line 24) | class GLColorOverlay {
method GLColorOverlay (line 65) | public GLColorOverlay(int color) {
method initGl (line 71) | public static void initGl() {
method draw (line 82) | public void draw(float[] mvpMatrix) {
method setColor (line 109) | public void setColor(int color) {
method destroy (line 113) | public void destroy() {
FILE: library/src/main/java/com/roger/missview/library/GLPicture.java
class GLPicture (line 28) | class GLPicture {
method initGl (line 93) | public static void initGl() {
method GLPicture (line 111) | public GLPicture(BitmapRegionLoader bitmapRegionLoader, int maxHeight) {
method GLPicture (line 166) | public GLPicture(Bitmap bitmap) {
method draw (line 210) | public void draw(float[] mvpMatrix, float alpha) {
method destroy (line 267) | public void destroy() {
FILE: library/src/main/java/com/roger/missview/library/GLTextureView.java
class GLTextureView (line 44) | public class GLTextureView extends TextureView implements TextureView.Su...
method GLTextureView (line 93) | public GLTextureView(Context context) {
method GLTextureView (line 102) | public GLTextureView(Context context, AttributeSet attrs) {
method finalize (line 107) | @Override
method init (line 120) | private void init() {
method setGLWrapper (line 137) | public void setGLWrapper(GLWrapper glWrapper) {
method setDebugFlags (line 150) | public void setDebugFlags(int debugFlags) {
method getDebugFlags (line 158) | public int getDebugFlags() {
method setPreserveEGLContextOnPause (line 180) | public void setPreserveEGLContextOnPause(boolean preserveOnPause) {
method getPreserveEGLContextOnPause (line 187) | public boolean getPreserveEGLContextOnPause() {
method setRenderer (line 217) | public void setRenderer(GLSurfaceView.Renderer renderer) {
method setEGLContextFactory (line 243) | public void setEGLContextFactory(EGLContextFactory factory) {
method setEGLWindowSurfaceFactory (line 257) | public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) {
method setEGLConfigChooser (line 274) | public void setEGLConfigChooser(EGLConfigChooser configChooser) {
method setEGLConfigChooser (line 293) | public void setEGLConfigChooser(boolean needDepth) {
method setEGLConfigChooser (line 310) | public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
method setEGLContextClientVersion (line 342) | public void setEGLContextClientVersion(int version) {
method setRenderMode (line 363) | public void setRenderMode(int renderMode) {
method getRenderMode (line 374) | public int getRenderMode() {
method requestRender (line 385) | public void requestRender() {
method onSurfaceTextureAvailable (line 389) | @Override
method onSurfaceTextureSizeChanged (line 394) | @Override
method onSizeChanged (line 399) | @Override
method onSurfaceTextureDestroyed (line 405) | @Override
method onSurfaceTextureUpdated (line 411) | @Override
method on (line 420) | public void on(SurfaceHolder holder) {
method onPause (line 430) | public void onPause() {
method onResume (line 441) | public void onResume() {
method queueEvent (line 451) | public void queueEvent(Runnable r) {
method onAttachedToWindow (line 459) | @Override
method onDetachedFromWindow (line 484) | @Override
type GLWrapper (line 519) | public interface GLWrapper {
method wrap (line 525) | GL wrap(GL gl);
type EGLContextFactory (line 534) | public interface EGLContextFactory {
method createContext (line 535) | EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eg...
method destroyContext (line 536) | void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context);
class DefaultContextFactory (line 539) | private class DefaultContextFactory implements EGLContextFactory {
method createContext (line 542) | public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLCo...
method destroyContext (line 550) | public void destroyContext(EGL10 egl, EGLDisplay display,
type EGLWindowSurfaceFactory (line 568) | public interface EGLWindowSurfaceFactory {
method createWindowSurface (line 572) | EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLCon...
method destroySurface (line 574) | void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface);
class DefaultWindowSurfaceFactory (line 577) | private static class DefaultWindowSurfaceFactory implements EGLWindowS...
method createWindowSurface (line 579) | public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
method destroySurface (line 596) | public void destroySurface(EGL10 egl, EGLDisplay display,
type EGLConfigChooser (line 609) | public interface EGLConfigChooser {
method chooseConfig (line 619) | EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
class BaseConfigChooser (line 622) | private abstract class BaseConfigChooser
method BaseConfigChooser (line 624) | public BaseConfigChooser(int[] configSpec) {
method chooseConfig (line 628) | public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
method chooseConfig (line 654) | abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
method filterConfigSpec (line 659) | private int[] filterConfigSpec(int[] configSpec) {
class ComponentSizeChooser (line 680) | private class ComponentSizeChooser extends BaseConfigChooser {
method ComponentSizeChooser (line 681) | public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
method chooseConfig (line 700) | @Override
method findConfigAttrib (line 726) | private int findConfigAttrib(EGL10 egl, EGLDisplay display,
class SimpleEGLConfigChooser (line 750) | private class SimpleEGLConfigChooser extends ComponentSizeChooser {
method SimpleEGLConfigChooser (line 751) | public SimpleEGLConfigChooser(boolean withDepthBuffer) {
class EglHelper (line 760) | private static class EglHelper {
method EglHelper (line 761) | public EglHelper(WeakReference<GLTextureView> glTextureViewWeakRef) {
method start (line 769) | public void start() {
method createSurface (line 824) | public boolean createSurface() {
method createGL (line 886) | GL createGL() {
method swap (line 914) | public int swap() {
method destroySurface (line 921) | public void destroySurface() {
method destroySurfaceImp (line 928) | private void destroySurfaceImp() {
method finish (line 941) | public void finish() {
method throwEglException (line 958) | private void throwEglException(String function) {
method throwEglException (line 962) | public static void throwEglException(String function, int error) {
method logEglErrorAsWarning (line 971) | public static void logEglErrorAsWarning(String tag, String function,...
method formatEglError (line 975) | public static String formatEglError(String function, int error) {
class GLThread (line 997) | static class GLThread extends Thread {
method GLThread (line 998) | GLThread(WeakReference<GLTextureView> glTextureViewWeakRef) {
method run (line 1007) | @Override
method stopEglSurfaceLocked (line 1027) | private void stopEglSurfaceLocked() {
method stopEglContextLocked (line 1038) | private void stopEglContextLocked() {
method guardedRun (line 1045) | private void guardedRun() throws InterruptedException {
method ableToDraw (line 1341) | public boolean ableToDraw() {
method readyToDraw (line 1345) | private boolean readyToDraw() {
method setRenderMode (line 1351) | public void setRenderMode(int renderMode) {
method getRenderMode (line 1361) | public int getRenderMode() {
method requestRender (line 1367) | public void requestRender() {
method surfaceCreated (line 1374) | public void surfaceCreated() {
method surfaceDestroyed (line 1394) | public void surfaceDestroyed() {
method onPause (line 1411) | public void onPause() {
method onResume (line 1431) | public void onResume() {
method onWindowResize (line 1453) | public void onWindowResize(int w, int h) {
method requestExitAndWait (line 1477) | public void requestExitAndWait() {
method requestReleaseEglContextLocked (line 1493) | public void requestReleaseEglContextLocked() {
method queueEvent (line 1502) | public void queueEvent(Runnable r) {
class LogWriter (line 1546) | static class LogWriter extends Writer {
method close (line 1548) | @Override public void close() {
method flush (line 1552) | @Override public void flush() {
method write (line 1556) | @Override public void write(char[] buf, int offset, int count) {
method flushBuilder (line 1568) | private void flushBuilder() {
method checkRenderThreadState (line 1579) | private void checkRenderThreadState() {
class GLThreadManager (line 1586) | private static class GLThreadManager {
method threadExiting (line 1589) | public synchronized void threadExiting(GLThread thread) {
method tryAcquireEglContextLocked (line 1607) | public boolean tryAcquireEglContextLocked(GLThread thread) {
method releaseEglContextLocked (line 1631) | public void releaseEglContextLocked(GLThread thread) {
method shouldReleaseEGLContextWhenPausing (line 1638) | public synchronized boolean shouldReleaseEGLContextWhenPausing() {
method shouldTerminateEGLWhenPausing (line 1645) | public synchronized boolean shouldTerminateEGLWhenPausing() {
method checkGLDriver (line 1650) | public synchronized void checkGLDriver(GL10 gl) {
method checkGLESVersion (line 1669) | private void checkGLESVersion() {
FILE: library/src/main/java/com/roger/missview/library/GLUtil.java
class GLUtil (line 27) | public class GLUtil {
method loadShader (line 31) | public static int loadShader(int type, String shaderCode) {
method createAndLinkProgram (line 43) | public static int createAndLinkProgram(int vertexShaderHandle, int fra...
method loadTexture (line 62) | public static int loadTexture(Bitmap bitmap) {
method checkGlError (line 93) | public static void checkGlError(String glOperation) {
method asFloatBuffer (line 99) | public static FloatBuffer asFloatBuffer(float[] array) {
method newFloatBuffer (line 106) | public static FloatBuffer newFloatBuffer(int size) {
FILE: library/src/main/java/com/roger/missview/library/MissView.java
class MissView (line 11) | public class MissView extends GLTextureView
method MissView (line 16) | public MissView(Context context) {
method MissView (line 21) | public MissView(Context context, AttributeSet attrs) {
method init (line 26) | private void init() {
method initPicture (line 34) | public void initPicture(String mPictureName) {
method initPicture (line 40) | public void initPicture(Bitmap mBitmap) {
method onSizeChanged (line 46) | @Override protected void onSizeChanged(int w, int h, int oldw, int old...
method onDetachedFromWindow (line 52) | @Override protected void onDetachedFromWindow() {
method queueEventOnGlThread (line 64) | @Override public void queueEventOnGlThread(Runnable runnable) {
method requestRender (line 71) | @Override public void requestRender() {
FILE: library/src/main/java/com/roger/missview/library/RenderController.java
class RenderController (line 25) | public abstract class RenderController {
method RenderController (line 32) | public RenderController(Context context, BlurRenderer renderer, Callba...
method destroy (line 38) | public void destroy() {
method openDownloadedCurrentArtwork (line 45) | protected abstract BitmapRegionLoader openDownloadedCurrentArtwork(boo...
method reloadCurrentArtwork (line 47) | public void reloadCurrentArtwork(final boolean forceReload) {
method setVisible (line 75) | public void setVisible(boolean visible) {
type Callbacks (line 91) | public static interface Callbacks {
method queueEventOnGlThread (line 92) | void queueEventOnGlThread(Runnable runnable);
method requestRender (line 94) | void requestRender();
FILE: library/src/main/java/com/roger/missview/library/util/ArtDetailViewport.java
class ArtDetailViewport (line 23) | public class ArtDetailViewport {
method getInstance (line 30) | public static ArtDetailViewport getInstance() {
method ArtDetailViewport (line 34) | private ArtDetailViewport() {
method getViewport (line 37) | public RectF getViewport(int id) {
method setViewport (line 41) | public ArtDetailViewport setViewport(int id, RectF viewport, boolean f...
method setViewport (line 46) | public ArtDetailViewport setViewport(int id, float left, float top, fl...
method isFromUser (line 53) | public boolean isFromUser() {
method setDefaultViewport (line 57) | public ArtDetailViewport setDefaultViewport(int id, float bitmapAspect...
FILE: library/src/main/java/com/roger/missview/library/util/BitmapRegionLoader.java
class BitmapRegionLoader (line 33) | public class BitmapRegionLoader {
method newInstance (line 43) | public static BitmapRegionLoader newInstance(InputStream in) {
method newInstance (line 47) | public static BitmapRegionLoader newInstance(InputStream in, int rotat...
method BitmapRegionLoader (line 66) | private BitmapRegionLoader(InputStream in) {
method decodeRegion (line 83) | public synchronized Bitmap decodeRegion(Rect rect, Options options) {
method getWidth (line 145) | public synchronized int getWidth() {
method getHeight (line 149) | public synchronized int getHeight() {
method destroy (line 153) | public synchronized void destroy() {
FILE: library/src/main/java/com/roger/missview/library/util/ImageBlurrer.java
class ImageBlurrer (line 28) | public class ImageBlurrer {
method ImageBlurrer (line 37) | public ImageBlurrer(Context context) {
method blurBitmap (line 43) | public Bitmap blurBitmap(Bitmap src, float radius, float desaturateAmo...
method destroy (line 87) | public void destroy() {
FILE: library/src/main/java/com/roger/missview/library/util/ImageUtil.java
class ImageUtil (line 22) | public class ImageUtil {
method calculateDarkness (line 24) | public static float calculateDarkness(Bitmap bitmap) {
method ImageUtil (line 48) | private ImageUtil() {
method calculateSampleSize (line 51) | public static int calculateSampleSize(int rawHeight, int targetHeight) {
FILE: library/src/main/java/com/roger/missview/library/util/MathUtil.java
class MathUtil (line 21) | public class MathUtil {
method constrain (line 22) | public static float constrain(float min, float max, float v) {
method interpolate (line 26) | public static float interpolate(float x1, float x2, float f) {
method uninterpolate (line 30) | public static float uninterpolate(float x1, float x2, float v) {
method dist (line 37) | public static float dist(float x, float y) {
method floorEven (line 41) | public static int floorEven(int num) {
method roundMult4 (line 45) | public static int roundMult4(int num) {
method isEven (line 49) | public static boolean isEven(int num) {
method MathUtil (line 53) | private MathUtil() {
FILE: library/src/main/java/com/roger/missview/library/util/TickingFloatAnimator.java
class TickingFloatAnimator (line 24) | public class TickingFloatAnimator {
method create (line 34) | public static TickingFloatAnimator create() {
method from (line 38) | public TickingFloatAnimator from(float startValue) {
method to (line 45) | public TickingFloatAnimator to(float endValue) {
method withDuration (line 50) | public TickingFloatAnimator withDuration(int duration) {
method withInterpolator (line 55) | public TickingFloatAnimator withInterpolator(TimeInterpolator interpol...
method withEndListener (line 60) | public TickingFloatAnimator withEndListener(Runnable listener) {
method cancel (line 65) | public void cancel() {
method tick (line 70) | public boolean tick() {
method start (line 101) | public void start() {
method isRunning (line 108) | public boolean isRunning() {
method currentValue (line 112) | public float currentValue() {
method TickingFloatAnimator (line 116) | private TickingFloatAnimator() {
FILE: library/src/main/java/com/roger/missview/library/util/UriUtil.java
class UriUtil (line 15) | public class UriUtil {
method getImageAbsolutePath (line 21) | @TargetApi(19)
method getDataColumn (line 67) | public static String getDataColumn(Context context, Uri uri, String se...
method isExternalStorageDocument (line 88) | public static boolean isExternalStorageDocument(Uri uri) {
method isDownloadsDocument (line 96) | public static boolean isDownloadsDocument(Uri uri) {
method isMediaDocument (line 104) | public static boolean isMediaDocument(Uri uri) {
method isGooglePhotosUri (line 112) | public static boolean isGooglePhotosUri(Uri uri) {
Condensed preview — 54 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (192K chars).
[
{
"path": ".gitignore",
"chars": 81,
"preview": ".gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n"
},
{
"path": ".idea/.name",
"chars": 8,
"preview": "MissView"
},
{
"path": ".idea/compiler.xml",
"chars": 709,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"CompilerConfiguration\">\n <option name"
},
{
"path": ".idea/copyright/profiles_settings.xml",
"chars": 74,
"preview": "<component name=\"CopyrightManager\">\n <settings default=\"\" />\n</component>"
},
{
"path": ".idea/encodings.xml",
"chars": 159,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"Encoding\">\n <file url=\"PROJECT\" chars"
},
{
"path": ".idea/gradle.xml",
"chars": 847,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"GradleSettings\">\n <option name=\"linke"
},
{
"path": ".idea/misc.xml",
"chars": 2629,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"EntryPointsManager\">\n <entry_points v"
},
{
"path": ".idea/modules.xml",
"chars": 470,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectModuleManager\">\n <modules>\n "
},
{
"path": ".idea/runConfigurations.xml",
"chars": 564,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"RunConfigurationProducerService\">\n <o"
},
{
"path": ".idea/vcs.xml",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": "MissView.iml",
"chars": 939,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\"MissView\" external.linked.project.path=\"$MODU"
},
{
"path": "README.md",
"chars": 2082,
"preview": "# MissView\nThis project is a part of Muzei,(https://github.com/romannurik/muzei) .<br>\nThanks for Roman Nurik..<br>\n\nI l"
},
{
"path": "build.gradle",
"chars": 572,
"preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n r"
},
{
"path": "demo/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "demo/build.gradle",
"chars": 616,
"preview": "apply plugin: 'com.android.application'\n\nandroid {\n compileSdkVersion 21\n buildToolsVersion \"21.1.2\"\n\n defaultC"
},
{
"path": "demo/demo.iml",
"chars": 8053,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\":demo\" external.linked.project.path=\"$MODULE_"
},
{
"path": "demo/proguard-rules.pro",
"chars": 680,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in F:"
},
{
"path": "demo/src/androidTest/java/com/roger/missview/ApplicationTest.java",
"chars": 349,
"preview": "package com.roger.missview;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"h"
},
{
"path": "demo/src/main/AndroidManifest.xml",
"chars": 847,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "demo/src/main/java/com/roger/missview/MainActivity.java",
"chars": 2125,
"preview": "package com.roger.missview;\n\nimport android.app.Activity;\nimport android.graphics.Bitmap;\nimport android.graphics.Bitmap"
},
{
"path": "demo/src/main/res/layout/activity_main.xml",
"chars": 430,
"preview": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tools=\"http://schemas.android.com/t"
},
{
"path": "demo/src/main/res/menu/menu_main.xml",
"chars": 361,
"preview": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app=\"http://schemas.android.com/apk/res-auto\""
},
{
"path": "demo/src/main/res/values/dimens.xml",
"chars": 211,
"preview": "<resources>\n <!-- Default screen margins, per the Android Design guidelines. -->\n <dimen name=\"activity_horizontal"
},
{
"path": "demo/src/main/res/values/strings.xml",
"chars": 178,
"preview": "<resources>\n <string name=\"app_name\">Missview</string>\n\n <string name=\"hello_world\">Hello world!</string>\n <str"
},
{
"path": "demo/src/main/res/values/styles.xml",
"chars": 194,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
},
{
"path": "demo/src/main/res/values-w820dp/dimens.xml",
"chars": 358,
"preview": "<resources>\n <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n (such as s"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 232,
"preview": "#Wed Apr 10 15:27:10 PDT 2013\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
},
{
"path": "gradle.properties",
"chars": 855,
"preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
},
{
"path": "gradlew",
"chars": 5080,
"preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n## Gradle start "
},
{
"path": "gradlew.bat",
"chars": 2314,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
},
{
"path": "library/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "library/build.gradle",
"chars": 2684,
"preview": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\napply plugin: 'com.jfrog.bintray'"
},
{
"path": "library/library.iml",
"chars": 7978,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\":library\" external.linked.project.path=\"$MODU"
},
{
"path": "library/proguard-rules.pro",
"chars": 680,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in F:"
},
{
"path": "library/src/androidTest/java/com/roger/missview/library/ApplicationTest.java",
"chars": 357,
"preview": "package com.roger.missview.library;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a"
},
{
"path": "library/src/main/AndroidManifest.xml",
"chars": 123,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.roger.missview.library\">\n</manifes"
},
{
"path": "library/src/main/java/com/roger/missview/library/BlurRenderer.java",
"chars": 21187,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/DemoRenderController.java",
"chars": 4011,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/GLColorOverlay.java",
"chars": 4107,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/GLPicture.java",
"chars": 10947,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/GLTextureView.java",
"chars": 66210,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/GLUtil.java",
"chars": 4030,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/MissView.java",
"chars": 2063,
"preview": "package com.roger.missview.library;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.open"
},
{
"path": "library/src/main/java/com/roger/missview/library/RenderController.java",
"chars": 3190,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/util/ArtDetailViewport.java",
"chars": 2403,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/util/BitmapRegionLoader.java",
"chars": 5639,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/util/ImageBlurrer.java",
"chars": 3252,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/util/ImageUtil.java",
"chars": 1702,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/util/MathUtil.java",
"chars": 1553,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/util/TickingFloatAnimator.java",
"chars": 3151,
"preview": "/*\n * Copyright 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "library/src/main/java/com/roger/missview/library/util/UriUtil.java",
"chars": 4604,
"preview": "package com.roger.missview.library.util;\n\nimport android.annotation.TargetApi;\nimport android.content.ContentUris;\nimpor"
},
{
"path": "settings.gradle",
"chars": 28,
"preview": "include ':library', ':demo'\n"
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the Rogero0o/MissView GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 54 files (177.8 KB), approximately 42.2k tokens, and a symbol index with 238 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.