Merge "Add SilkFX demo app"

This commit is contained in:
TreeHugger Robot
2020-08-06 22:06:07 +00:00
committed by Android (Google) Code Review
19 changed files with 1025 additions and 0 deletions

22
tests/SilkFX/Android.bp Normal file
View File

@@ -0,0 +1,22 @@
//
// Copyright (C) 2010 The Android Open Source Project
//
// 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.
//
android_test {
name: "SilkFX",
srcs: ["**/*.java", "**/*.kt"],
platform_apis: true,
certificate: "platform",
}

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.silkfx">
<uses-sdk android:minSdkVersion="30"/>
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
<application android:label="SilkFX"
android:theme="@android:style/Theme.Material">
<activity android:name=".Main"
android:label="SilkFX Demos"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".app.CommonDemoActivity" />
<activity android:name=".hdr.GlowActivity"
android:label="Glow Examples"/>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 The Android Open Source Project
~
~ 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.android.test.silkfx.hdr.BlingyNotification
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:src="@drawable/dark_notification" />
<com.android.test.silkfx.hdr.BlingyNotification
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:src="@drawable/light_notification" />
</LinearLayout>

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 The Android Open Source Project
~
~ 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.
-->
<com.android.test.silkfx.common.ColorModeControls
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/current_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/mode_default"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Default (sRGB)" />
<Button
android:id="@+id/mode_wide"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Wide Gamut (P3)" />
<Button
android:id="@+id/mode_hdr"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="HDR" />
<Button
android:id="@+id/mode_hdr10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="HDR10" />
</LinearLayout>
</com.android.test.silkfx.common.ColorModeControls>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 The Android Open Source Project
~
~ 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/color_mode_controls" />
<FrameLayout android:id="@+id/demo_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.android.test.silkfx.common.HDRIndicator
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="8dp" />
</LinearLayout>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 The Android Open Source Project
~
~ 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/color_mode_controls" />
<com.android.test.silkfx.hdr.GlowingCard
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="8dp" />
<com.android.test.silkfx.hdr.GlowingCard
android:id="@+id/card2"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="8dp"/>
<com.android.test.silkfx.hdr.RadialGlow
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_margin="8dp" />
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.android.test.silkfx.common.HDRIndicator
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="8dp" />
</LinearLayout>

View File

@@ -0,0 +1,125 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseExpandableListAdapter
import android.widget.ExpandableListView
import android.widget.TextView
import com.android.test.silkfx.app.CommonDemoActivity
import com.android.test.silkfx.app.EXTRA_LAYOUT
import com.android.test.silkfx.app.EXTRA_TITLE
import com.android.test.silkfx.hdr.GlowActivity
import kotlin.reflect.KClass
class Demo(val name: String, val makeIntent: (Context) -> Intent) {
constructor(name: String, activity: KClass<out Activity>) : this(name, { context ->
Intent(context, activity.java)
})
constructor(name: String, layout: Int) : this(name, { context ->
Intent(context, CommonDemoActivity::class.java).apply {
putExtra(EXTRA_LAYOUT, layout)
putExtra(EXTRA_TITLE, name)
}
})
}
data class DemoGroup(val groupName: String, val demos: List<Demo>)
private val AllDemos = listOf(
DemoGroup("HDR", listOf(
Demo("Glow", GlowActivity::class),
Demo("Blingy Notifications", R.layout.bling_notifications)
))
)
class Main : Activity() {
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val list = ExpandableListView(this)
setContentView(list)
val inflater = LayoutInflater.from(this)
list.setAdapter(object : BaseExpandableListAdapter() {
override fun getGroup(groupPosition: Int): DemoGroup {
return AllDemos[groupPosition]
}
override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean = true
override fun hasStableIds(): Boolean = true
override fun getGroupView(
groupPosition: Int,
isExpanded: Boolean,
convertView: View?,
parent: ViewGroup?
): View {
val view = (convertView ?: inflater.inflate(
android.R.layout.simple_expandable_list_item_1, parent, false)) as TextView
view.text = AllDemos[groupPosition].groupName
return view
}
override fun getChildrenCount(groupPosition: Int): Int {
return AllDemos[groupPosition].demos.size
}
override fun getChild(groupPosition: Int, childPosition: Int): Demo {
return AllDemos[groupPosition].demos[childPosition]
}
override fun getGroupId(groupPosition: Int): Long = groupPosition.toLong()
override fun getChildView(
groupPosition: Int,
childPosition: Int,
isLastChild: Boolean,
convertView: View?,
parent: ViewGroup?
): View {
val view = (convertView ?: inflater.inflate(
android.R.layout.simple_expandable_list_item_1, parent, false)) as TextView
view.text = AllDemos[groupPosition].demos[childPosition].name
return view
}
override fun getChildId(groupPosition: Int, childPosition: Int): Long {
return (groupPosition.toLong() shl 32) or childPosition.toLong()
}
override fun getGroupCount(): Int {
return AllDemos.size
}
})
list.setOnChildClickListener { _, _, groupPosition, childPosition, _ ->
val demo = AllDemos[groupPosition].demos[childPosition]
startActivity(demo.makeIntent(this))
return@setOnChildClickListener true
}
AllDemos.forEachIndexed { index, _ -> list.expandGroup(index) }
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.app
import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
open class BaseDemoActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val inflater = LayoutInflater.from(this)
inflater.factory2 = object : LayoutInflater.Factory2 {
private val sClassPrefixList = arrayOf(
"android.widget.",
"android.webkit.",
"android.app.",
null
)
override fun onCreateView(
parent: View?,
name: String,
context: Context,
attrs: AttributeSet
): View? {
return onCreateView(name, context, attrs)
}
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
for (prefix in sClassPrefixList) {
try {
val view = inflater.createView(name, prefix, attrs)
if (view != null) {
if (view is WindowObserver) {
view.setWindow(window)
}
return view
}
} catch (e: ClassNotFoundException) { }
}
return null
}
}
}
override fun onStart() {
super.onStart()
actionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
onBackPressed()
return true
}
return super.onOptionsItemSelected(item)
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.app
import com.android.test.silkfx.R
import android.os.Bundle
import android.view.LayoutInflater
const val EXTRA_LAYOUT = "layout"
const val EXTRA_TITLE = "title"
class CommonDemoActivity : BaseDemoActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val extras = intent.extras ?: return finish()
val layout = extras.getInt(EXTRA_LAYOUT, -1)
if (layout == -1) {
finish()
return
}
val title = extras.getString(EXTRA_TITLE, "SilkFX")
window.setTitle(title)
setContentView(R.layout.common_base)
actionBar?.title = title
LayoutInflater.from(this).inflate(layout, findViewById(R.id.demo_container), true)
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.app
import android.view.Window
interface WindowObserver {
fun setWindow(window: Window)
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.common
import android.content.Context
import android.graphics.Color
import android.graphics.ColorSpace
import android.util.AttributeSet
import android.view.View
open class BaseDrawingView : View {
val scRGB = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)
val bt2020 = ColorSpace.get(ColorSpace.Named.BT2020)
val lab = ColorSpace.get(ColorSpace.Named.CIE_LAB)
val density: Float
val dp: Int.() -> Float
fun color(red: Float, green: Float, blue: Float, alpha: Float = 1f): Long {
return Color.pack(red, green, blue, alpha, scRGB)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
setWillNotDraw(false)
isClickable = true
density = resources.displayMetrics.density
dp = { this * density }
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.common
import android.content.Context
import android.content.pm.ActivityInfo
import android.hardware.display.DisplayManager
import android.util.AttributeSet
import android.view.Window
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.android.test.silkfx.R
import com.android.test.silkfx.app.WindowObserver
import java.lang.Exception
class ColorModeControls : LinearLayout, WindowObserver {
private val COLOR_MODE_HDR10 = 3
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
displayManager = context.getSystemService(DisplayManager::class.java)!!
}
private var window: Window? = null
private var currentMode: TextView? = null
private val displayManager: DisplayManager
override fun onFinishInflate() {
super.onFinishInflate()
val window = window ?: throw IllegalStateException("Failed to attach window")
currentMode = findViewById(R.id.current_mode)!!
setColorMode(window.colorMode)
findViewById<Button>(R.id.mode_default)!!.setOnClickListener {
setColorMode(ActivityInfo.COLOR_MODE_DEFAULT)
}
findViewById<Button>(R.id.mode_wide)!!.setOnClickListener {
setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT)
}
findViewById<Button>(R.id.mode_hdr)!!.setOnClickListener {
setColorMode(ActivityInfo.COLOR_MODE_HDR)
}
findViewById<Button>(R.id.mode_hdr10)!!.setOnClickListener {
setColorMode(COLOR_MODE_HDR10)
}
}
private fun setColorMode(newMode: Int) {
val window = window!!
// Need to do this before setting the colorMode, as setting the colorMode will
// trigger the attribute change listener
if (newMode == ActivityInfo.COLOR_MODE_HDR ||
newMode == COLOR_MODE_HDR10) {
setBrightness(1.0f)
} else {
setBrightness(.4f)
}
window.colorMode = newMode
currentMode?.run {
text = "Current Mode: " + when (newMode) {
ActivityInfo.COLOR_MODE_DEFAULT -> "Default/SRGB"
ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT -> "Wide Gamut"
ActivityInfo.COLOR_MODE_HDR -> "HDR (sdr white point 150)"
COLOR_MODE_HDR10 -> "HDR10 (sdr white point 150)"
else -> "Unknown"
}
}
}
override fun setWindow(window: Window) {
this.window = window
}
private fun setBrightness(level: Float) {
// To keep window state in sync
window?.attributes?.screenBrightness = level
invalidate()
// To force an 'immediate' snap to what we want
// Imperfect, but close enough, synchronization by waiting for frame commit to set the value
viewTreeObserver.registerFrameCommitCallback {
try {
displayManager.setTemporaryBrightness(level)
} catch (ex: Exception) {
// Ignore a permission denied rejection - it doesn't meaningfully change much
}
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.common
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.ColorSpace
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
class HDRIndicator(context: Context) : View(context) {
constructor(context: Context, attrs: AttributeSet?) : this(context)
val scRGB = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val paint = Paint()
paint.isAntiAlias = true
val rect = RectF(0f, 0f, width.toFloat(), height.toFloat())
paint.textSize = height.toFloat()
canvas.drawColor(Color.pack(1f, 1f, 1f, 1f, scRGB))
paint.setColor(Color.pack(1.1f, 1.1f, 1.1f, 1f, scRGB))
canvas.drawText("H", rect.left, rect.bottom, paint)
paint.setColor(Color.pack(1.2f, 1.2f, 1.2f, 1f, scRGB))
canvas.drawText("D", rect.left + height.toFloat(), rect.bottom, paint)
paint.setColor(Color.pack(1.3f, 1.3f, 1.3f, 1f, scRGB))
canvas.drawText("R", rect.left + height.toFloat() * 2, rect.bottom, paint)
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.hdr
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BlendMode
import android.graphics.Canvas
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.Shader
import android.graphics.drawable.BitmapDrawable
import android.util.AttributeSet
import com.android.test.silkfx.common.BaseDrawingView
class BlingyNotification : BaseDrawingView {
private val image: Bitmap?
private val bounds = Rect()
private val paint = Paint()
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
val typed = context.obtainStyledAttributes(attrs, intArrayOf(android.R.attr.src))
val drawable = typed.getDrawable(0)
image = if (drawable is BitmapDrawable) {
drawable.bitmap
} else {
null
}
typed.recycle()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val image = image ?: return super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
// Currently only used in this mode, so that's all we'll bother to support
if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
val width = MeasureSpec.getSize(widthMeasureSpec)
var height = image.height * width / image.width
if (heightMode == MeasureSpec.AT_MOST) {
height = minOf(MeasureSpec.getSize(heightMeasureSpec), height)
}
setMeasuredDimension(width, height)
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
bounds.set(0, 0, w, h)
paint.shader = LinearGradient(0f, 0f, w.toFloat(), 0f,
longArrayOf(
color(1f, 1f, 1f, 0f),
color(1f, 1f, 1f, .4f),
color(2f, 2f, 2f, .8f),
color(1f, 1f, 1f, .4f),
color(1f, 1f, 1f, 0f)
),
floatArrayOf(.2f, .4f, .5f, .6f, .8f),
Shader.TileMode.CLAMP)
paint.blendMode = BlendMode.PLUS
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val image = image ?: return
canvas.drawBitmap(image, null, bounds, null)
canvas.save()
val frac = ((drawingTime % 2000) / 300f) - 1f
canvas.translate(width * frac, 0f)
canvas.rotate(-45f)
canvas.drawPaint(paint)
canvas.restore()
invalidate()
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.hdr
import android.os.Bundle
import com.android.test.silkfx.R
import com.android.test.silkfx.app.BaseDemoActivity
class GlowActivity : BaseDemoActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.hdr_glows)
findViewById<GlowingCard>(R.id.card2)!!.setGlowIntensity(4f)
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.hdr
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.RectF
import android.graphics.Shader
import android.util.AttributeSet
import com.android.test.silkfx.common.BaseDrawingView
class GlowingCard : BaseDrawingView {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
val radius: Float
var COLOR_MAXIMIZER = 1f
init {
radius = 10.dp()
}
fun setGlowIntensity(multiplier: Float) {
COLOR_MAXIMIZER = multiplier
invalidate()
}
override fun setPressed(pressed: Boolean) {
super.setPressed(pressed)
invalidate()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val paint = Paint()
paint.isAntiAlias = true
val rect = RectF(0f, 0f, width.toFloat(), height.toFloat())
val glowColor = Color.pack(.5f * COLOR_MAXIMIZER, .4f * COLOR_MAXIMIZER,
.75f * COLOR_MAXIMIZER, 1f, scRGB)
if (isPressed) {
paint.setColor(Color.pack(2f, 2f, 2f, 1f, scRGB))
paint.strokeWidth = 4.dp()
paint.style = Paint.Style.FILL
paint.shader = LinearGradient(rect.left, rect.bottom, rect.right, rect.top,
glowColor,
Color.pack(0f, 0f, 0f, 0f, scRGB),
Shader.TileMode.CLAMP)
canvas.drawRoundRect(rect, radius, radius, paint)
}
rect.inset(3.dp(), 3.dp())
paint.setColor(Color.pack(.14f, .14f, .14f, .8f, scRGB))
paint.style = Paint.Style.FILL
paint.shader = null
canvas.drawRoundRect(rect, radius, radius, paint)
rect.inset(5.dp(), 5.dp())
paint.textSize = 14.dp()
paint.isFakeBoldText = true
paint.color = Color.WHITE
canvas.drawText("glow = scRGB{${Color.red(glowColor)}, ${Color.green(glowColor)}, " +
"${Color.blue(glowColor)}}", rect.left, rect.centerY(), paint)
canvas.drawText("(press to activate)", rect.left, rect.bottom, paint)
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.android.test.silkfx.hdr
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RadialGradient
import android.graphics.RectF
import android.graphics.Shader
import android.util.AttributeSet
import com.android.test.silkfx.common.BaseDrawingView
import kotlin.math.min
class RadialGlow : BaseDrawingView {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
var glowToggle = false
val glowColor = color(4f, 3.3f, 2.8f)
val bgColor = color(.15f, .15f, .15f)
val fgColor = color(.51f, .52f, .50f, .4f)
var glow: RadialGradient
init {
glow = RadialGradient(0f, 0f, 100.dp(), glowColor, bgColor, Shader.TileMode.CLAMP)
isClickable = true
setOnClickListener {
glowToggle = !glowToggle
invalidate()
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
glow = RadialGradient(0f, 0f,
min(w, h).toFloat(), glowColor, bgColor, Shader.TileMode.CLAMP)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val radius = 10.dp()
val paint = Paint()
paint.isDither = true
paint.isAntiAlias = true
paint.textSize = 18.dp()
paint.textAlign = Paint.Align.CENTER
val rect = RectF(0f, 0f, width.toFloat(), height.toFloat())
paint.setColor(bgColor)
canvas.drawRoundRect(rect, radius, radius, paint)
if (glowToggle) {
paint.shader = glow
canvas.save()
val frac = (drawingTime % 5000) / 5000f
canvas.translate(rect.width() * frac, rect.height() - (rect.height() * frac))
canvas.drawPaint(paint)
canvas.restore()
paint.shader = null
invalidate()
}
paint.setColor(fgColor)
val innerRect = RectF(rect)
innerRect.inset(rect.width() / 4, rect.height() / 4)
canvas.drawRoundRect(innerRect, radius, radius, paint)
paint.setColor(color(1f, 1f, 1f))
canvas.drawText("Tap to toggle animation", rect.centerX(), innerRect.top - 4.dp(), paint)
canvas.drawText("Outside text", rect.centerX(), rect.bottom - 4.dp(), paint)
canvas.drawText("Inside text", innerRect.centerX(), innerRect.bottom - 4.dp(), paint)
}
}