package beru;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import org.xmlpull.v1.XmlPullParserException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.util.Log;
import android.view.View;
import beru.WidgetTest.R;
public final class Graphics {
public static void modulateHSV(
int[] pixels,
byte[] chunk, // Nine Patch PNG npTc chunk
final int w,
final int h,
double hue,
double sat,
double val
) {
float[] hsv = new float[3];
hue = hue * 360.0;
if (chunk != null) {
// final byte wasDeserialized = chunk[0];
final byte numXDivs = chunk[1];
final byte numYDivs = chunk[2];
final byte numColors = chunk[3];
int offset = 4 + 4 * (7 + numXDivs + numYDivs);
for (int i=0; i<numColors; ++i) {
int pos = offset + 4 * i;
int b = chunk[pos+0] & 0xFF;
int g = chunk[pos+1] & 0xFF;
int r = chunk[pos+2] & 0xFF;
int a = chunk[pos+3] & 0xFF;
if ((b<2) && (g|r|a) == 0) {
continue;
}
int v = a << 24 | r << 16 | g << 8 | b;
Color.colorToHSV(v, hsv);
hsv[0] += hue;
hsv[1] += sat;
hsv[2] += val;
v = Color.HSVToColor(a, hsv);
chunk[pos+0] = (byte) ((v >> 0) & 0xff);
chunk[pos+1] = (byte) ((v >> 8) & 0xff);
chunk[pos+2] = (byte) ((v >> 16) & 0xff);
}
}
int pos = 0;
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
final int c = pixels[pos+x];
final int a = (c >> 24) & 0xff;
Color.colorToHSV(c, hsv);
hsv[0] += hue;
hsv[1] += sat;
hsv[2] += val;
pixels[pos+x] = Color.HSVToColor(a, hsv);
}
pos += w;
}
}
public static void alterBackground(View view, int xmlId) {
final class BackgroundSetting {
String name;
String drawable;
float hue = 0.0f;
float sat = 0.0f;
float val = 0.0f;
}
final class TargetSetting {
String id;
String background;
}
Resources res = view.getContext().getResources();
XmlResourceParser xrp = res.getXml(xmlId);
HashMap<String, BackgroundSetting> backgrounds = new HashMap<String, BackgroundSetting>();
ArrayList<TargetSetting> targets = new ArrayList<TargetSetting>();
// TODO: get attributes using reflection, or generate Java source code automatically
int event;
try {
event = xrp.getEventType();
while (event != XmlResourceParser.END_DOCUMENT) {
if (event == XmlResourceParser.START_TAG) {
String name = xrp.getName();
int attrCount = xrp.getAttributeCount();
if (name.equals("background")) {
BackgroundSetting s = new BackgroundSetting();
for (int i=0; i<attrCount; ++i) {
String aName = xrp.getAttributeName(i);
if (aName.equals("name")) {
s.name = xrp.getAttributeValue(i);
}else if (aName.equals("drawable")) {
s.drawable = xrp.getAttributeValue(i);
}else if (aName.equals("hue")) {
s.hue = xrp.getAttributeFloatValue(i, 0.0f);
}else if (aName.equals("sat")) {
s.sat = xrp.getAttributeFloatValue(i, 0.0f);
}else if (aName.equals("val")) {
s.val = xrp.getAttributeFloatValue(i, 0.0f);
}
}
backgrounds.put(s.name, s);
}else if (name.equals("target")) {
TargetSetting s = new TargetSetting();
for (int i=0; i<attrCount; ++i) {
String aName = xrp.getAttributeName(i);
if (aName.equals("id")) {
s.id = xrp.getAttributeValue(i);
}else if (aName.equals("background")) {
s.background = xrp.getAttributeValue(i);
}
}
targets.add(s);
}
}
event = xrp.next();
}
xrp.close();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
RMap.init(R.class, RMap.sInts);
HashMap<String, Integer> rIds = RMap.sInts.get("id");
HashMap<String, Integer> rDrawables = RMap.sInts.get("drawable");
for (int i=0; i<targets.size(); ++i) {
TargetSetting t = targets.get(i);
if (!rIds.containsKey(t.id)) {
Log.i("", "id:" + t.id + " not found in resource");
continue;
}
View target = view.findViewById(rIds.get(t.id));
if (target == null) {
Log.i("", "id:" + t.id + " not found in view");
continue;
}
if (!backgrounds.containsKey(t.background)) {
Log.i("", t.background + " not found in xml");
continue;
}
BackgroundSetting bs = backgrounds.get(t.background);
if (!rDrawables.containsKey(bs.drawable)) {
Log.i("", "drawable:" + bs.drawable + " not found in resource");
continue;
}
final int drwableId = rDrawables.get(bs.drawable);
Bitmap tmpBmp = BitmapFactory.decodeResource(res, drwableId);
Bitmap bmp = tmpBmp.copy(tmpBmp.getConfig(), true);
int w = bmp.getWidth();
int h = bmp.getHeight();
int[] pixels = new int[w * h];
byte[] chunk = tmpBmp.getNinePatchChunk();
bmp.getPixels(pixels, 0, w, 0, 0, w, h);
modulateHSV(pixels, chunk, w, h, bs.hue, bs.sat, bs.val);
bmp.setPixels(pixels, 0, w, 0, 0, w, h);
Drawable bg = target.getBackground();
Rect padding = new Rect();
bg.getPadding(padding);
NinePatchDrawable npd = new NinePatchDrawable(
res,
bmp,
chunk,
padding,
"");
target.setBackgroundDrawable(npd);
}
}
}
|