summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt36
-rwxr-xr-xcore/java/android/util/PropertyValueModel.java143
-rwxr-xr-xcore/java/android/util/ValueModel.java74
-rw-r--r--core/java/android/widget/CheckBox.java23
-rw-r--r--core/java/android/widget/EditText.java23
-rw-r--r--core/java/android/widget/SeekBar.java20
-rwxr-xr-xcore/java/android/widget/ValueEditor.java53
-rw-r--r--libs/hwui/FontRenderer.cpp10
-rw-r--r--libs/hwui/FontRenderer.h4
-rw-r--r--libs/hwui/OpenGLRenderer.cpp77
-rw-r--r--libs/hwui/OpenGLRenderer.h20
-rw-r--r--libs/hwui/TextDropShadowCache.cpp6
-rw-r--r--libs/hwui/TextDropShadowCache.h21
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java73
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java6
-rw-r--r--tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs92
16 files changed, 625 insertions, 56 deletions
diff --git a/api/current.txt b/api/current.txt
index 29e468b39307..fc067747b6c4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22826,6 +22826,17 @@ package android.util {
method public void set(T, V);
}
+ public class PropertyValueModel extends android.util.ValueModel {
+ method public T get();
+ method public H getHost();
+ method public android.util.Property<H, T> getProperty();
+ method public java.lang.Class<T> getType();
+ method public static android.util.PropertyValueModel<H, T> of(H, android.util.Property<H, T>);
+ method public static android.util.PropertyValueModel<H, T> of(H, java.lang.Class<T>, java.lang.String);
+ method public static android.util.PropertyValueModel of(java.lang.Object, java.lang.String);
+ method public void set(T);
+ }
+
public class SparseArray implements java.lang.Cloneable {
ctor public SparseArray();
ctor public SparseArray(int);
@@ -22974,6 +22985,14 @@ package android.util {
field public int type;
}
+ public abstract class ValueModel {
+ ctor protected ValueModel();
+ method public abstract T get();
+ method public abstract java.lang.Class<T> getType();
+ method public abstract void set(T);
+ field public static final android.util.ValueModel EMPTY;
+ }
+
public class Xml {
method public static android.util.AttributeSet asAttributeSet(org.xmlpull.v1.XmlPullParser);
method public static android.util.Xml.Encoding findEncodingByName(java.lang.String) throws java.io.UnsupportedEncodingException;
@@ -27395,10 +27414,12 @@ package android.widget {
method public abstract void onSelectedDayChange(android.widget.CalendarView, int, int, int);
}
- public class CheckBox extends android.widget.CompoundButton {
+ public class CheckBox extends android.widget.CompoundButton implements android.widget.ValueEditor {
ctor public CheckBox(android.content.Context);
ctor public CheckBox(android.content.Context, android.util.AttributeSet);
ctor public CheckBox(android.content.Context, android.util.AttributeSet, int);
+ method public android.util.ValueModel<java.lang.Boolean> getValueModel();
+ method public void setValueModel(android.util.ValueModel<java.lang.Boolean>);
}
public abstract interface Checkable {
@@ -27571,14 +27592,16 @@ package android.widget {
method public void setSize(int, int);
}
- public class EditText extends android.widget.TextView {
+ public class EditText extends android.widget.TextView implements android.widget.ValueEditor {
ctor public EditText(android.content.Context);
ctor public EditText(android.content.Context, android.util.AttributeSet);
ctor public EditText(android.content.Context, android.util.AttributeSet, int);
method public void extendSelection(int);
+ method public android.util.ValueModel<java.lang.CharSequence> getValueModel();
method public void selectAll();
method public void setSelection(int, int);
method public void setSelection(int);
+ method public void setValueModel(android.util.ValueModel<java.lang.CharSequence>);
}
public abstract interface ExpandableListAdapter {
@@ -28595,11 +28618,13 @@ package android.widget {
method public abstract java.lang.Object[] getSections();
}
- public class SeekBar extends android.widget.AbsSeekBar {
+ public class SeekBar extends android.widget.AbsSeekBar implements android.widget.ValueEditor {
ctor public SeekBar(android.content.Context);
ctor public SeekBar(android.content.Context, android.util.AttributeSet);
ctor public SeekBar(android.content.Context, android.util.AttributeSet, int);
+ method public android.util.ValueModel<java.lang.Integer> getValueModel();
method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener);
+ method public void setValueModel(android.util.ValueModel<java.lang.Integer>);
}
public static abstract interface SeekBar.OnSeekBarChangeListener {
@@ -29171,6 +29196,11 @@ package android.widget {
method public android.widget.TextView getText2();
}
+ public abstract interface ValueEditor {
+ method public abstract android.util.ValueModel<T> getValueModel();
+ method public abstract void setValueModel(android.util.ValueModel<T>);
+ }
+
public class VideoView extends android.view.SurfaceView implements android.widget.MediaController.MediaPlayerControl {
ctor public VideoView(android.content.Context);
ctor public VideoView(android.content.Context, android.util.AttributeSet);
diff --git a/core/java/android/util/PropertyValueModel.java b/core/java/android/util/PropertyValueModel.java
new file mode 100755
index 000000000000..eb9c47d0c379
--- /dev/null
+++ b/core/java/android/util/PropertyValueModel.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 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 android.util;
+
+/**
+ * A value model for a {@link Property property} of a host object. This class can be used for
+ * both reflective and non-reflective property implementations.
+ *
+ * @param <H> the host type, where the host is the object that holds this property
+ * @param <T> the value type
+ *
+ * @see Property
+ * @see ValueModel
+ */
+public class PropertyValueModel<H, T> extends ValueModel<T> {
+ private final H mHost;
+ private final Property<H, T> mProperty;
+
+ private PropertyValueModel(H host, Property<H, T> property) {
+ mProperty = property;
+ mHost = host;
+ }
+
+ /**
+ * Returns the host.
+ *
+ * @return the host
+ */
+ public H getHost() {
+ return mHost;
+ }
+
+ /**
+ * Returns the property.
+ *
+ * @return the property
+ */
+ public Property<H, T> getProperty() {
+ return mProperty;
+ }
+
+ @Override
+ public Class<T> getType() {
+ return mProperty.getType();
+ }
+
+ @Override
+ public T get() {
+ return mProperty.get(mHost);
+ }
+
+ @Override
+ public void set(T value) {
+ mProperty.set(mHost, value);
+ }
+
+ /**
+ * Return an appropriate PropertyValueModel for this host and property.
+ *
+ * @param host the host
+ * @param property the property
+ * @return the value model
+ */
+ public static <H, T> PropertyValueModel<H, T> of(H host, Property<H, T> property) {
+ return new PropertyValueModel<H, T>(host, property);
+ }
+
+ /**
+ * Return a PropertyValueModel for this {@code host} and a
+ * reflective property, constructed from this {@code propertyType} and {@code propertyName}.
+ *
+ * @param host
+ * @param propertyType the property type
+ * @param propertyName the property name
+ * @return a value model with this host and a reflective property with this type and name
+ *
+ * @see Property#of
+ */
+ public static <H, T> PropertyValueModel<H, T> of(H host, Class<T> propertyType,
+ String propertyName) {
+ return of(host, Property.of((Class<H>) host.getClass(), propertyType, propertyName));
+ }
+
+ private static Class getNullaryMethodReturnType(Class c, String name) {
+ try {
+ return c.getMethod(name).getReturnType();
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ private static Class getFieldType(Class c, String name) {
+ try {
+ return c.getField(name).getType();
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+
+ private static String capitalize(String name) {
+ if (name.isEmpty()) {
+ return name;
+ }
+ return Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ }
+
+ /**
+ * Return a PropertyValueModel for this {@code host} and and {@code propertyName}.
+ *
+ * @param host the host
+ * @param propertyName the property name
+ * @return a value model with this host and a reflective property with this name
+ */
+ public static PropertyValueModel of(Object host, String propertyName) {
+ Class clazz = host.getClass();
+ String suffix = capitalize(propertyName);
+ Class propertyType = getNullaryMethodReturnType(clazz, "get" + suffix);
+ if (propertyType == null) {
+ propertyType = getNullaryMethodReturnType(clazz, "is" + suffix);
+ }
+ if (propertyType == null) {
+ propertyType = getFieldType(clazz, propertyName);
+ }
+ if (propertyType == null) {
+ throw new NoSuchPropertyException(propertyName);
+ }
+ return of(host, propertyType, propertyName);
+ }
+}
diff --git a/core/java/android/util/ValueModel.java b/core/java/android/util/ValueModel.java
new file mode 100755
index 000000000000..4789682ea496
--- /dev/null
+++ b/core/java/android/util/ValueModel.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 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 android.util;
+
+/**
+ * A ValueModel is an abstraction for a 'slot' or place in memory in which a value
+ * may be stored and retrieved. A common implementation of ValueModel is a regular property of
+ * an object, whose value may be retrieved by calling the appropriate <em>getter</em>
+ * method and set by calling the corresponding <em>setter</em> method.
+ *
+ * @param <T> the value type
+ *
+ * @see PropertyValueModel
+ */
+public abstract class ValueModel<T> {
+ /**
+ * The empty model should be used in place of {@code null} to indicate that a
+ * model has not been set. The empty model has no value and does nothing when it is set.
+ */
+ public static final ValueModel EMPTY = new ValueModel() {
+ @Override
+ public Class getType() {
+ return Object.class;
+ }
+
+ @Override
+ public Object get() {
+ return null;
+ }
+
+ @Override
+ public void set(Object value) {
+
+ }
+ };
+
+ protected ValueModel() {
+ }
+
+ /**
+ * Returns the type of this property.
+ *
+ * @return the property type
+ */
+ public abstract Class<T> getType();
+
+ /**
+ * Returns the value of this property.
+ *
+ * @return the property value
+ */
+ public abstract T get();
+
+ /**
+ * Sets the value of this property.
+ *
+ * @param value the new value for this property
+ */
+ public abstract void set(T value);
+} \ No newline at end of file
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index 858c415d0f08..6d292dcafa83 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.util.ValueModel;
/**
@@ -55,7 +56,9 @@ import android.view.accessibility.AccessibilityNodeInfo;
* {@link android.R.styleable#View View Attributes}
* </p>
*/
-public class CheckBox extends CompoundButton {
+public class CheckBox extends CompoundButton implements ValueEditor<Boolean> {
+ private ValueModel<Boolean> mValueModel = ValueModel.EMPTY;
+
public CheckBox(Context context) {
this(context, null);
}
@@ -79,4 +82,22 @@ public class CheckBox extends CompoundButton {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(CheckBox.class.getName());
}
+
+ @Override
+ public ValueModel<Boolean> getValueModel() {
+ return mValueModel;
+ }
+
+ @Override
+ public void setValueModel(ValueModel<Boolean> valueModel) {
+ mValueModel = valueModel;
+ setChecked(mValueModel.get());
+ }
+
+ @Override
+ public boolean performClick() {
+ boolean handled = super.performClick();
+ mValueModel.set(isChecked());
+ return handled;
+ }
}
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 2fd876822368..8686177c6247 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -17,6 +17,7 @@
package android.widget;
import android.content.Context;
+import android.graphics.Rect;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
@@ -24,6 +25,7 @@ import android.text.TextUtils;
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.MovementMethod;
import android.util.AttributeSet;
+import android.util.ValueModel;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -47,7 +49,9 @@ import android.view.accessibility.AccessibilityNodeInfo;
* {@link android.R.styleable#TextView TextView Attributes},
* {@link android.R.styleable#View View Attributes}
*/
-public class EditText extends TextView {
+public class EditText extends TextView implements ValueEditor<CharSequence> {
+ private ValueModel<CharSequence> mValueModel = ValueModel.EMPTY;
+
public EditText(Context context) {
this(context, null);
}
@@ -128,4 +132,21 @@ public class EditText extends TextView {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(EditText.class.getName());
}
+
+ @Override
+ public ValueModel<CharSequence> getValueModel() {
+ return mValueModel;
+ }
+
+ @Override
+ public void setValueModel(ValueModel<CharSequence> valueModel) {
+ mValueModel = valueModel;
+ setText(mValueModel.get());
+ }
+
+ @Override
+ void sendAfterTextChanged(Editable text) {
+ super.sendAfterTextChanged(text);
+ mValueModel.set(text);
+ }
}
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index 2737f9414c46..a6486a827af5 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -18,6 +18,7 @@ package android.widget;
import android.content.Context;
import android.util.AttributeSet;
+import android.util.ValueModel;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -33,7 +34,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
*
* @attr ref android.R.styleable#SeekBar_thumb
*/
-public class SeekBar extends AbsSeekBar {
+public class SeekBar extends AbsSeekBar implements ValueEditor<Integer> {
/**
* A callback that notifies clients when the progress level has been
@@ -69,8 +70,9 @@ public class SeekBar extends AbsSeekBar {
void onStopTrackingTouch(SeekBar seekBar);
}
+ private ValueModel<Integer> mValueModel = ValueModel.EMPTY;
private OnSeekBarChangeListener mOnSeekBarChangeListener;
-
+
public SeekBar(Context context) {
this(context, null);
}
@@ -89,9 +91,23 @@ public class SeekBar extends AbsSeekBar {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
+ if (fromUser) {
+ mValueModel.set(getProgress());
+ }
}
}
+ @Override
+ public ValueModel<Integer> getValueModel() {
+ return mValueModel;
+ }
+
+ @Override
+ public void setValueModel(ValueModel<Integer> valueModel) {
+ mValueModel = valueModel;
+ setProgress(mValueModel.get());
+ }
+
/**
* Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
* provides notifications of when the user starts and stops a touch gesture within the SeekBar.
diff --git a/core/java/android/widget/ValueEditor.java b/core/java/android/widget/ValueEditor.java
new file mode 100755
index 000000000000..2b91abf9b8ff
--- /dev/null
+++ b/core/java/android/widget/ValueEditor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 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 android.widget;
+
+import android.util.ValueModel;
+
+/**
+ * An interface for editors of simple values. Classes implementing this interface are normally
+ * UI controls (subclasses of {@link android.view.View View}) that can provide a suitable
+ * user interface to display and edit values of the specified type. This interface is
+ * intended to describe editors for simple types, like {@code boolean}, {@code int} or
+ * {@code String}, where the values themselves are immutable.
+ * <p>
+ * For example, {@link android.widget.CheckBox CheckBox} implements
+ * this interface for the Boolean type as it is capable of providing an appropriate
+ * mechanism for displaying and changing the value of a Boolean property.
+ *
+ * @param <T> the value type that this editor supports
+ */
+public interface ValueEditor<T> {
+ /**
+ * Return the last value model that was set. If no value model has been set, the editor
+ * should return the value {@link android.util.ValueModel#EMPTY}.
+ *
+ * @return the value model
+ */
+ public ValueModel<T> getValueModel();
+
+ /**
+ * Sets the value model for this editor. When the value model is set, the editor should
+ * retrieve the value from the value model, using {@link android.util.ValueModel#get()},
+ * and set its internal state accordingly. Likewise, when the editor's internal state changes
+ * it should update the value model by calling {@link android.util.ValueModel#set(T)}
+ * with the appropriate value.
+ *
+ * @param valueModel the new value model for this editor.
+ */
+ public void setValueModel(ValueModel<T> valueModel);
+}
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index eeb37cbe08c1..7f0ed7309b62 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -288,13 +288,13 @@ void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len
}
void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
- int numGlyphs, Rect *bounds) {
+ int numGlyphs, Rect *bounds, const float* positions) {
if (bounds == NULL) {
ALOGE("No return rectangle provided to measure text");
return;
}
bounds->set(1e6, -1e6, -1e6, 1e6);
- render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, NULL);
+ render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, positions);
}
void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
@@ -1007,7 +1007,7 @@ void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) {
}
FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
- uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius) {
+ uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) {
checkInit();
if (!mCurrentFont) {
@@ -1025,7 +1025,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
mBounds = NULL;
Rect bounds;
- mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
+ mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions);
uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
@@ -1039,7 +1039,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
int penY = radius - bounds.bottom;
mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
- dataBuffer, paddedWidth, paddedHeight);
+ Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions);
blurImage(dataBuffer, paddedWidth, paddedHeight, radius);
DropShadow image;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index b7b4ec9683f9..9ed69325c914 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -184,7 +184,7 @@ protected:
uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
- int numGlyphs, Rect *bounds);
+ int numGlyphs, Rect *bounds, const float* positions);
Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
@@ -273,7 +273,7 @@ public:
// After renderDropShadow returns, the called owns the memory in DropShadow.image
// and is responsible for releasing it when it's done with it
DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
- uint32_t len, int numGlyphs, uint32_t radius);
+ uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
GLuint getTexture(bool linearFiltering = false) {
checkInit();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 5fa3d3ebc9dc..6d781c77fa7a 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2303,6 +2303,44 @@ status_t OpenGLRenderer::drawRect(float left, float top, float right, float bott
return DrawGlInfo::kStatusDrew;
}
+void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
+ const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
+ float x, float y) {
+ mCaches.activeTexture(0);
+
+ // NOTE: The drop shadow will not perform gamma correction
+ // if shader-based correction is enabled
+ mCaches.dropShadowCache.setFontRenderer(fontRenderer);
+ const ShadowTexture* shadow = mCaches.dropShadowCache.get(
+ paint, text, bytesCount, count, mShadowRadius, positions);
+ const AutoTexture autoCleanup(shadow);
+
+ const float sx = x - shadow->left + mShadowDx;
+ const float sy = y - shadow->top + mShadowDy;
+
+ const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
+ int shadowColor = mShadowColor;
+ if (mShader) {
+ shadowColor = 0xffffffff;
+ }
+
+ setupDraw();
+ setupDrawWithTexture(true);
+ setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
+ setupDrawColorFilter();
+ setupDrawShader();
+ setupDrawBlending(true, mode);
+ setupDrawProgram();
+ setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
+ setupDrawTexture(shadow->id);
+ setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawShaderUniforms();
+ setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+}
+
status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
const float* positions, SkPaint* paint) {
if (text == NULL || count == 0 || mSnapshot->isIgnored() ||
@@ -2331,6 +2369,11 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
+ if (CC_UNLIKELY(mHasShadow)) {
+ drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
+ 0.0f, 0.0f);
+ }
+
// Pick the appropriate texture filtering
bool linearFilter = mSnapshot->transform->changesBounds();
if (pureTranslate && !linearFilter) {
@@ -2424,39 +2467,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
getAlphaAndMode(paint, &alpha, &mode);
if (CC_UNLIKELY(mHasShadow)) {
- mCaches.activeTexture(0);
-
- // NOTE: The drop shadow will not perform gamma correction
- // if shader-based correction is enabled
- mCaches.dropShadowCache.setFontRenderer(fontRenderer);
- const ShadowTexture* shadow = mCaches.dropShadowCache.get(
- paint, text, bytesCount, count, mShadowRadius);
- const AutoTexture autoCleanup(shadow);
-
- const float sx = oldX - shadow->left + mShadowDx;
- const float sy = oldY - shadow->top + mShadowDy;
-
- const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
- int shadowColor = mShadowColor;
- if (mShader) {
- shadowColor = 0xffffffff;
- }
-
- setupDraw();
- setupDrawWithTexture(true);
- setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
- setupDrawColorFilter();
- setupDrawShader();
- setupDrawBlending(true, mode);
- setupDrawProgram();
- setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height);
- setupDrawTexture(shadow->id);
- setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
- setupDrawShaderUniforms();
- setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+ drawTextShadow(paint, text, bytesCount, count, NULL, fontRenderer, alpha, mode, oldX, oldY);
}
// Pick the appropriate texture filtering
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 1926575bccc2..441e9fd6c8d8 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -498,6 +498,24 @@ private:
void drawTextDecorations(const char* text, int bytesCount, float length,
float x, float y, SkPaint* paint);
+ /**
+ * Draws shadow layer on text (with optional positions).
+ *
+ * @param paint The paint to draw the shadow with
+ * @param text The text to draw
+ * @param bytesCount The number of bytes in the text
+ * @param count The number of glyphs in the text
+ * @param positions The x, y positions of individual glyphs (or NULL)
+ * @param fontRenderer The font renderer object
+ * @param alpha The alpha value for drawing the shadow
+ * @param mode The xfermode for drawing the shadow
+ * @param x The x coordinate where the shadow will be drawn
+ * @param y The y coordinate where the shadow will be drawn
+ */
+ void drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
+ const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
+ float x, float y);
+
/**
* Draws a path texture. Path textures are alpha8 bitmaps that need special
* compositing to apply colors/filters/etc.
@@ -507,7 +525,7 @@ private:
* @param y The y coordinate where the texture will be drawn
* @param paint The paint to draw the texture with
*/
- void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
+ void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
/**
* Resets the texture coordinates stored in mMeshVertices. Setting the values
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index bef137371d44..93aa8a5c0af3 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -102,13 +102,13 @@ void TextDropShadowCache::clear() {
}
ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len,
- int numGlyphs, uint32_t radius) {
- ShadowText entry(paint, radius, len, text);
+ int numGlyphs, uint32_t radius, const float* positions) {
+ ShadowText entry(paint, radius, len, text, positions);
ShadowTexture* texture = mCache.get(entry);
if (!texture) {
FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(paint, text, 0,
- len, numGlyphs, radius);
+ len, numGlyphs, radius, positions);
texture = new ShadowTexture;
texture->left = shadow.penX;
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index e2bdde1eca89..bae0c49349f6 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -35,8 +35,9 @@ struct ShadowText {
ShadowText(): radius(0), len(0), textSize(0.0f), typeface(NULL) {
}
- ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText):
- radius(radius), len(len) {
+ ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText,
+ const float* positions):
+ radius(radius), len(len), positions(positions) {
// TODO: Propagate this through the API, we should not cast here
text = (const char16_t*) srcText;
@@ -66,11 +67,18 @@ struct ShadowText {
uint32_t italicStyle;
uint32_t scaleX;
const char16_t* text;
+ const float* positions;
String16 str;
+ Vector<float> positionsCopy;
void copyTextLocally() {
str.setTo((const char16_t*) text, len >> 1);
text = str.string();
+ if (positions != NULL) {
+ positionsCopy.clear();
+ positionsCopy.appendArray(positions, len);
+ positions = positionsCopy.array();
+ }
}
bool operator<(const ShadowText& rhs) const {
@@ -81,7 +89,12 @@ struct ShadowText {
LTE_INT(flags) {
LTE_INT(italicStyle) {
LTE_INT(scaleX) {
- return memcmp(text, rhs.text, len) < 0;
+ int cmp = memcmp(text, rhs.text, len);
+ if (cmp < 0) return true;
+ if (cmp == 0 && rhs.positions != NULL) {
+ if (positions == NULL) return true;
+ return memcmp(positions, rhs.positions, len << 2) < 0;
+ }
}
}
}
@@ -117,7 +130,7 @@ public:
void operator()(ShadowText& text, ShadowTexture*& texture);
ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len,
- int numGlyphs, uint32_t radius);
+ int numGlyphs, uint32_t radius, const float* positions);
/**
* Clears the cache. This causes all textures to be deleted.
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java
new file mode 100644
index 000000000000..cd54c2eb5bc1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 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.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Grain extends TestBase {
+ private ScriptC_grain mScript;
+ private Allocation mNoise;
+ private Allocation mNoise2;
+
+
+ public boolean onBar1Setup(SeekBar b, TextView t) {
+ t.setText("Strength");
+ b.setProgress(50);
+ return true;
+ }
+
+ public void onBar1Changed(int progress) {
+ float s = progress / 100.0f;
+ mScript.set_gNoiseStrength(s);
+ }
+
+ public void createTest(android.content.res.Resources res) {
+ int width = mInPixelsAllocation.getType().getX();
+ int height = mInPixelsAllocation.getType().getY();
+
+ Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+ tb.setX(width);
+ tb.setY(height);
+ mNoise = Allocation.createTyped(mRS, tb.create());
+ mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+ mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+ mScript.set_gWidth(width);
+ mScript.set_gHeight(height);
+ mScript.set_gNoiseStrength(0.5f);
+ mScript.set_gBlendSource(mNoise);
+ mScript.set_gNoise(mNoise2);
+ }
+
+ public void runTest() {
+ mScript.forEach_genRand(mNoise);
+ mScript.forEach_blend9(mNoise2);
+ mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index e085582c3027..3a9838bf790a 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -140,6 +140,9 @@ public class ImageProcessingActivity extends Activity
case 5:
mTest = new Greyscale();
break;
+ case 6:
+ mTest = new Grain();
+ break;
}
mTest.createBaseTest(this, mBitmapIn);
@@ -152,13 +155,14 @@ public class ImageProcessingActivity extends Activity
}
void setupTests() {
- mTestNames = new String[6];
+ mTestNames = new String[7];
mTestNames[0] = "Levels Vec3 Relaxed";
mTestNames[1] = "Levels Vec4 Relaxed";
mTestNames[2] = "Levels Vec3 Full";
mTestNames[3] = "Levels Vec4 Full";
mTestNames[4] = "Blur radius 25";
mTestNames[5] = "Greyscale";
+ mTestNames[6] = "Grain";
mTestSpinner.setAdapter(new ArrayAdapter<String>(
this, R.layout.spinner_layout, mTestNames));
}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs
new file mode 100644
index 000000000000..97ae4fb3a38d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
+
+void genRand(uchar *out) {
+ *out = (uchar)rsRand(0xff);
+}
+
+/*
+ * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
+ * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
+ * small values are not calculated to gain efficiency.
+ * The order ot pixels represented in this matrix is:
+ * 1 2 3
+ * 4 0 5
+ * 6 7 8
+ * and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
+ * However, since most of the valus are identical, we only use the first three
+ * entries and the entries corresponding to the pixels is:
+ * 1 2 1
+ * 2 0 2
+ * 1 2 1
+ */
+
+int32_t gWidth;
+int32_t gHeight;
+
+rs_allocation gBlendSource;
+void blend9(uchar *out, uint32_t x, uint32_t y) {
+ uint32_t x1 = min(x+1, (uint32_t)gWidth);
+ uint32_t x2 = max(x-1, (uint32_t)0);
+ uint32_t y1 = min(y+1, (uint32_t)gHeight);
+ uint32_t y2 = max(y-1, (uint32_t)0);
+
+ uint p00 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0];
+ uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0];
+ uint p02 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0];
+ uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0];
+ uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0];
+ uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0];
+ uint p20 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0];
+ uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0];
+ uint p22 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0];
+
+ p00 += p01;
+ p02 += p10;
+ p11 += p12;
+ p20 += p21;
+
+ p22 += p00;
+ p02 += p11;
+
+ p20 += p22;
+ p20 += p02;
+
+ *out = (uchar)(p20 >> 10);
+}
+
+float gNoiseStrength;
+
+rs_allocation gNoise;
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+ float4 ip = convert_float4(*in);
+ float pnoise = (float) ((uchar *)rsGetElementAt(gNoise, x, y))[0];
+
+ float energy_level = ip.r + ip.g + ip.b;
+ float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
+ pnoise = (pnoise - 128.f) * energy_mask;
+
+ ip += pnoise * gNoiseStrength;
+ ip = clamp(ip, 0.f, 255.f);
+
+ uchar4 p = convert_uchar4(ip);
+ p.a = 0xff;
+ *out = p;
+}