refactor source tree organization, switch to meson

This commit is contained in:
Mis012
2022-10-02 23:06:56 +02:00
parent 2f785e2a59
commit 449090143e
296 changed files with 171615 additions and 69 deletions

View File

@@ -0,0 +1,336 @@
/*
* Copyright (C) 2006 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.content.res;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* File descriptor of an entry in the AssetManager. This provides your own
* opened FileDescriptor that can be used to read the data, as well as the
* offset and length of that entry's data in the file.
*/
public class AssetFileDescriptor implements Closeable {
/**
* Length used with {@link #AssetFileDescriptor(ParcelFileDescriptor, long, long)}
* and {@link #getDeclaredLength} when a length has not been declared. This means
* the data extends to the end of the file.
*/
public static final long UNKNOWN_LENGTH = -1;
private final ParcelFileDescriptor mFd;
private final long mStartOffset;
private final long mLength;
private final Bundle mExtras;
/**
* Create a new AssetFileDescriptor from the given values.
*
* @param fd The underlying file descriptor.
* @param startOffset The location within the file that the asset starts.
* This must be 0 if length is UNKNOWN_LENGTH.
* @param length The number of bytes of the asset, or
* {@link #UNKNOWN_LENGTH} if it extends to the end of the file.
*/
public AssetFileDescriptor(ParcelFileDescriptor fd, long startOffset,
long length) {
this(fd, startOffset, length, null);
}
/**
* Create a new AssetFileDescriptor from the given values.
*
* @param fd The underlying file descriptor.
* @param startOffset The location within the file that the asset starts.
* This must be 0 if length is UNKNOWN_LENGTH.
* @param length The number of bytes of the asset, or
* {@link #UNKNOWN_LENGTH} if it extends to the end of the file.
* @param extras additional details that can be used to interpret the
* underlying file descriptor. May be null.
*/
public AssetFileDescriptor(ParcelFileDescriptor fd, long startOffset,
long length, Bundle extras) {
if (fd == null) {
throw new IllegalArgumentException("fd must not be null");
}
if (length < 0 && startOffset != 0) {
throw new IllegalArgumentException(
"startOffset must be 0 when using UNKNOWN_LENGTH");
}
mFd = fd;
mStartOffset = startOffset;
mLength = length;
mExtras = extras;
}
/**
* The AssetFileDescriptor contains its own ParcelFileDescriptor, which
* in addition to the normal FileDescriptor object also allows you to close
* the descriptor when you are done with it.
*/
public ParcelFileDescriptor getParcelFileDescriptor() {
return mFd;
}
/**
* Returns the FileDescriptor that can be used to read the data in the
* file.
*/
public FileDescriptor getFileDescriptor() {
return mFd.getFileDescriptor();
}
/**
* Returns the byte offset where this asset entry's data starts.
*/
public long getStartOffset() {
return mStartOffset;
}
/**
* Returns any additional details that can be used to interpret the
* underlying file descriptor. May be null.
*/
public Bundle getExtras() {
return mExtras;
}
/**
* Returns the total number of bytes of this asset entry's data. May be
* {@link #UNKNOWN_LENGTH} if the asset extends to the end of the file.
* If the AssetFileDescriptor was constructed with {@link #UNKNOWN_LENGTH},
* this will use {@link ParcelFileDescriptor#getStatSize()
* ParcelFileDescriptor.getStatSize()} to find the total size of the file,
* returning that number if found or {@link #UNKNOWN_LENGTH} if it could
* not be determined.
*
* @see #getDeclaredLength()
*/
public long getLength() {
if (mLength >= 0) {
return mLength;
}
long len = mFd.getStatSize();
return len >= 0 ? len : UNKNOWN_LENGTH;
}
/**
* Return the actual number of bytes that were declared when the
* AssetFileDescriptor was constructed. Will be
* {@link #UNKNOWN_LENGTH} if the length was not declared, meaning data
* should be read to the end of the file.
*
* @see #getDeclaredLength()
*/
public long getDeclaredLength() {
return mLength;
}
/**
* Convenience for calling <code>getParcelFileDescriptor().close()</code>.
*/
@Override
public void close() throws IOException {
mFd.close();
}
/**
* Create and return a new auto-close input stream for this asset. This
* will either return a full asset {@link AutoCloseInputStream}, or
* an underlying {@link ParcelFileDescriptor.AutoCloseInputStream
* ParcelFileDescriptor.AutoCloseInputStream} depending on whether the
* the object represents a complete file or sub-section of a file. You
* should only call this once for a particular asset.
*/
public FileInputStream createInputStream() throws IOException {
if (mLength < 0) {
return new ParcelFileDescriptor.AutoCloseInputStream(mFd);
}
return new AutoCloseInputStream(this);
}
/**
* Create and return a new auto-close output stream for this asset. This
* will either return a full asset {@link AutoCloseOutputStream}, or
* an underlying {@link ParcelFileDescriptor.AutoCloseOutputStream
* ParcelFileDescriptor.AutoCloseOutputStream} depending on whether the
* the object represents a complete file or sub-section of a file. You
* should only call this once for a particular asset.
*/
public FileOutputStream createOutputStream() throws IOException {
if (mLength < 0) {
return new ParcelFileDescriptor.AutoCloseOutputStream(mFd);
}
return new AutoCloseOutputStream(this);
}
@Override
public String toString() {
return "{AssetFileDescriptor: " + mFd
+ " start=" + mStartOffset + " len=" + mLength + "}";
}
/**
* An InputStream you can create on a ParcelFileDescriptor, which will
* take care of calling {@link ParcelFileDescriptor#close
* ParcelFileDescritor.close()} for you when the stream is closed.
*/
public static class AutoCloseInputStream
extends ParcelFileDescriptor.AutoCloseInputStream {
private long mRemaining;
public AutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
super(fd.getParcelFileDescriptor());
super.skip(fd.getStartOffset());
mRemaining = (int)fd.getLength();
}
@Override
public int available() throws IOException {
return mRemaining >= 0
? (mRemaining < 0x7fffffff ? (int)mRemaining : 0x7fffffff)
: super.available();
}
@Override
public int read() throws IOException {
byte[] buffer = new byte[1];
int result = read(buffer, 0, 1);
return result == -1 ? -1 : buffer[0] & 0xff;
}
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
if (mRemaining >= 0) {
if (mRemaining == 0) return -1;
if (count > mRemaining) count = (int)mRemaining;
int res = super.read(buffer, offset, count);
if (res >= 0) mRemaining -= res;
return res;
}
return super.read(buffer, offset, count);
}
@Override
public int read(byte[] buffer) throws IOException {
return read(buffer, 0, buffer.length);
}
@Override
public long skip(long count) throws IOException {
if (mRemaining >= 0) {
if (mRemaining == 0) return -1;
if (count > mRemaining) count = mRemaining;
long res = super.skip(count);
if (res >= 0) mRemaining -= res;
return res;
}
return super.skip(count);
}
@Override
public void mark(int readlimit) {
if (mRemaining >= 0) {
// Not supported.
return;
}
super.mark(readlimit);
}
@Override
public boolean markSupported() {
if (mRemaining >= 0) {
return false;
}
return super.markSupported();
}
@Override
public synchronized void reset() throws IOException {
if (mRemaining >= 0) {
// Not supported.
return;
}
super.reset();
}
}
/**
* An OutputStream you can create on a ParcelFileDescriptor, which will
* take care of calling {@link ParcelFileDescriptor#close
* ParcelFileDescritor.close()} for you when the stream is closed.
*/
public static class AutoCloseOutputStream
extends ParcelFileDescriptor.AutoCloseOutputStream {
private long mRemaining;
public AutoCloseOutputStream(AssetFileDescriptor fd) throws IOException {
super(fd.getParcelFileDescriptor());
if (fd.getParcelFileDescriptor().seekTo(fd.getStartOffset()) < 0) {
throw new IOException("Unable to seek");
}
mRemaining = (int)fd.getLength();
}
@Override
public void write(byte[] buffer, int offset, int count) throws IOException {
if (mRemaining >= 0) {
if (mRemaining == 0) return;
if (count > mRemaining) count = (int)mRemaining;
super.write(buffer, offset, count);
mRemaining -= count;
return;
}
super.write(buffer, offset, count);
}
@Override
public void write(byte[] buffer) throws IOException {
if (mRemaining >= 0) {
if (mRemaining == 0) return;
int count = buffer.length;
if (count > mRemaining) count = (int)mRemaining;
super.write(buffer);
mRemaining -= count;
return;
}
super.write(buffer);
}
@Override
public void write(int oneByte) throws IOException {
if (mRemaining >= 0) {
if (mRemaining == 0) return;
super.write(oneByte);
mRemaining--;
return;
}
super.write(oneByte);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,300 @@
/*
* Copyright (C) 2007 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.content.res;
import com.android.internal.util.ArrayUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.StateSet;
import android.util.Xml;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Arrays;
/**
*
* Lets you map {@link android.view.View} state sets to colors.
*
* {@link android.content.res.ColorStateList}s are created from XML resource files defined in the
* "color" subdirectory directory of an application's resource directory. The XML file contains
* a single "selector" element with a number of "item" elements inside. For example:
*
* <pre>
* &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
* &lt;item android:state_focused="true" android:color="@color/testcolor1"/&gt;
* &lt;item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /&gt;
* &lt;item android:state_enabled="false" android:color="@color/testcolor3" /&gt;
* &lt;item android:color="@color/testcolor5"/&gt;
* &lt;/selector&gt;
* </pre>
*
* This defines a set of state spec / color pairs where each state spec specifies a set of
* states that a view must either be in or not be in and the color specifies the color associated
* with that spec. The list of state specs will be processed in order of the items in the XML file.
* An item with no state spec is considered to match any set of states and is generally useful as
* a final item to be used as a default. Note that if you have such an item before any other items
* in the list then any subsequent items will end up being ignored.
* <p>For more information, see the guide to <a
* href="{@docRoot}guide/topics/resources/color-list-resource.html">Color State
* List Resource</a>.</p>
*/
public class ColorStateList {
private int[][] mStateSpecs; // must be parallel to mColors
private int[] mColors; // must be parallel to mStateSpecs
private int mDefaultColor = 0xffff0000;
private static final int[][] EMPTY = new int[][] { new int[0] };
private static final SparseArray<WeakReference<ColorStateList>> sCache =
new SparseArray<WeakReference<ColorStateList>>();
private ColorStateList() { }
/**
* Creates a ColorStateList that returns the specified mapping from
* states to colors.
*/
public ColorStateList(int[][] states, int[] colors) {
mStateSpecs = states;
mColors = colors;
if (states.length > 0) {
mDefaultColor = colors[0];
for (int i = 0; i < states.length; i++) {
if (states[i].length == 0) {
mDefaultColor = colors[i];
}
}
}
}
/**
* Creates or retrieves a ColorStateList that always returns a single color.
*/
public static ColorStateList valueOf(int color) {
// TODO: should we collect these eventually?
synchronized (sCache) {
WeakReference<ColorStateList> ref = sCache.get(color);
ColorStateList csl = ref != null ? ref.get() : null;
if (csl != null) {
return csl;
}
csl = new ColorStateList(EMPTY, new int[] { color });
sCache.put(color, new WeakReference<ColorStateList>(csl));
return csl;
}
}
/**
* Create a ColorStateList from an XML document, given a set of {@link Resources}.
*/
public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
throws XmlPullParserException, IOException {
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
}
if (type != XmlPullParser.START_TAG) {
throw new XmlPullParserException("No start tag found");
}
return createFromXmlInner(r, parser, attrs);
}
/* Create from inside an XML document. Called on a parser positioned at
* a tag in an XML document, tries to create a ColorStateList from that tag.
* Returns null if the tag is not a valid ColorStateList.
*/
private static ColorStateList createFromXmlInner(Resources r, XmlPullParser parser,
AttributeSet attrs) throws XmlPullParserException, IOException {
ColorStateList colorStateList;
final String name = parser.getName();
if (name.equals("selector")) {
colorStateList = new ColorStateList();
} else {
throw new XmlPullParserException(
parser.getPositionDescription() + ": invalid drawable tag " + name);
}
colorStateList.inflate(r, parser, attrs);
return colorStateList;
}
/**
* Creates a new ColorStateList that has the same states and
* colors as this one but where each color has the specified alpha value
* (0-255).
*/
public ColorStateList withAlpha(int alpha) {
int[] colors = new int[mColors.length];
int len = colors.length;
for (int i = 0; i < len; i++) {
colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
}
return new ColorStateList(mStateSpecs, colors);
}
/**
* Fill in this object based on the contents of an XML "selector" element.
*/
private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
throws XmlPullParserException, IOException {
int type;
final int innerDepth = parser.getDepth()+1;
int depth;
int listAllocated = 20;
int listSize = 0;
int[] colorList = new int[listAllocated];
int[][] stateSpecList = new int[listAllocated][];
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth=parser.getDepth()) >= innerDepth
|| type != XmlPullParser.END_TAG)) {
if (type != XmlPullParser.START_TAG) {
continue;
}
if (depth > innerDepth || !parser.getName().equals("item")) {
continue;
}
int colorRes = 0;
int color = 0xffff0000;
boolean haveColor = false;
int i;
int j = 0;
final int numAttrs = attrs.getAttributeCount();
int[] stateSpec = new int[numAttrs];
for (i = 0; i < numAttrs; i++) {
final int stateResId = attrs.getAttributeNameResource(i);
if (stateResId == 0) break;
if (stateResId == com.android.internal.R.attr.color) {
colorRes = attrs.getAttributeResourceValue(i, 0);
if (colorRes == 0) {
color = attrs.getAttributeIntValue(i, color);
haveColor = true;
}
} else {
stateSpec[j++] = attrs.getAttributeBooleanValue(i, false)
? stateResId
: -stateResId;
}
}
stateSpec = StateSet.trimStateSet(stateSpec, j);
if (colorRes != 0) {
color = r.getColor(colorRes);
} else if (!haveColor) {
throw new XmlPullParserException(
parser.getPositionDescription()
+ ": <item> tag requires a 'android:color' attribute.");
}
if (listSize == 0 || stateSpec.length == 0) {
mDefaultColor = color;
}
if (listSize + 1 >= listAllocated) {
listAllocated = ArrayUtils.idealIntArraySize(listSize + 1);
int[] ncolor = new int[listAllocated];
System.arraycopy(colorList, 0, ncolor, 0, listSize);
int[][] nstate = new int[listAllocated][];
System.arraycopy(stateSpecList, 0, nstate, 0, listSize);
colorList = ncolor;
stateSpecList = nstate;
}
colorList[listSize] = color;
stateSpecList[listSize] = stateSpec;
listSize++;
}
mColors = new int[listSize];
mStateSpecs = new int[listSize][];
System.arraycopy(colorList, 0, mColors, 0, listSize);
System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
}
public boolean isStateful() {
return mStateSpecs.length > 1;
}
/**
* Return the color associated with the given set of {@link android.view.View} states.
*
* @param stateSet an array of {@link android.view.View} states
* @param defaultColor the color to return if there's not state spec in this
* {@link ColorStateList} that matches the stateSet.
*
* @return the color associated with that set of states in this {@link ColorStateList}.
*/
public int getColorForState(int[] stateSet, int defaultColor) {
final int setLength = mStateSpecs.length;
for (int i = 0; i < setLength; i++) {
int[] stateSpec = mStateSpecs[i];
if (StateSet.stateSetMatches(stateSpec, stateSet)) {
return mColors[i];
}
}
return defaultColor;
}
/**
* Return the default color in this {@link ColorStateList}.
*
* @return the default color in this {@link ColorStateList}.
*/
public int getDefaultColor() {
return mDefaultColor;
}
public String toString() {
return "ColorStateList{" +
"mStateSpecs=" + Arrays.deepToString(mStateSpecs) +
"mColors=" + Arrays.toString(mColors) +
"mDefaultColor=" + mDefaultColor + '}';
}
public int describeContents() {
return 0;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,492 @@
/*
* Copyright (C) 2006 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.content.res;
//import android.graphics.Color;
//import android.text.*;
//import android.text.style.*;
import android.util.Log;
import android.util.SparseArray;
//import android.graphics.Paint;
//import android.graphics.Rect;
//import android.graphics.Typeface;
import java.util.Arrays;
/**
* Conveniences for retrieving data out of a compiled string resource.
*
* {@hide}
*/
final class StringBlock {
private static final String TAG = "AssetManager";
private static final boolean localLOGV = false;
private final int mNative;
private final boolean mUseSparse;
private final boolean mOwnsNative;
private CharSequence[] mStrings;
private SparseArray<CharSequence> mSparseStrings;
// StyleIDs mStyleIDs = null;
public StringBlock(byte[] data, boolean useSparse) {
mNative = nativeCreate(data, 0, data.length);
mUseSparse = useSparse;
mOwnsNative = true;
if (localLOGV) Log.v(TAG, "Created string block " + this
+ ": " + nativeGetSize(mNative));
}
public StringBlock(byte[] data, int offset, int size, boolean useSparse) {
mNative = nativeCreate(data, offset, size);
mUseSparse = useSparse;
mOwnsNative = true;
if (localLOGV) Log.v(TAG, "Created string block " + this
+ ": " + nativeGetSize(mNative));
}
public CharSequence get(int idx) {/*
synchronized (this) {
if (mStrings != null) {
CharSequence res = mStrings[idx];
if (res != null) {
return res;
}
} else if (mSparseStrings != null) {
CharSequence res = mSparseStrings.get(idx);
if (res != null) {
return res;
}
} else {
final int num = nativeGetSize(mNative);
if (mUseSparse && num > 250) {
mSparseStrings = new SparseArray<CharSequence>();
} else {
mStrings = new CharSequence[num];
}
}
String str = nativeGetString(mNative, idx);
CharSequence res = str;
int[] style = nativeGetStyle(mNative, idx);
if (localLOGV) Log.v(TAG, "Got string: " + str);
if (localLOGV) Log.v(TAG, "Got styles: " + Arrays.toString(style));
if (style != null) {
if (mStyleIDs == null) {
mStyleIDs = new StyleIDs();
}
// the style array is a flat array of <type, start, end> hence
// the magic constant 3.
for (int styleIndex = 0; styleIndex < style.length; styleIndex += 3) {
int styleId = style[styleIndex];
if (styleId == mStyleIDs.boldId || styleId == mStyleIDs.italicId
|| styleId == mStyleIDs.underlineId || styleId == mStyleIDs.ttId
|| styleId == mStyleIDs.bigId || styleId == mStyleIDs.smallId
|| styleId == mStyleIDs.subId || styleId == mStyleIDs.supId
|| styleId == mStyleIDs.strikeId || styleId == mStyleIDs.listItemId
|| styleId == mStyleIDs.marqueeId) {
// id already found skip to next style
continue;
}
String styleTag = nativeGetString(mNative, styleId);
if (styleTag.equals("b")) {
mStyleIDs.boldId = styleId;
} else if (styleTag.equals("i")) {
mStyleIDs.italicId = styleId;
} else if (styleTag.equals("u")) {
mStyleIDs.underlineId = styleId;
} else if (styleTag.equals("tt")) {
mStyleIDs.ttId = styleId;
} else if (styleTag.equals("big")) {
mStyleIDs.bigId = styleId;
} else if (styleTag.equals("small")) {
mStyleIDs.smallId = styleId;
} else if (styleTag.equals("sup")) {
mStyleIDs.supId = styleId;
} else if (styleTag.equals("sub")) {
mStyleIDs.subId = styleId;
} else if (styleTag.equals("strike")) {
mStyleIDs.strikeId = styleId;
} else if (styleTag.equals("li")) {
mStyleIDs.listItemId = styleId;
} else if (styleTag.equals("marquee")) {
mStyleIDs.marqueeId = styleId;
}
}
res = applyStyles(str, style, mStyleIDs);
}
if (mStrings != null) mStrings[idx] = res;
else mSparseStrings.put(idx, res);
return res;
}
*/return null;}
/*
protected void finalize() throws Throwable {
try {
super.finalize();
} finally {
if (mOwnsNative) {
nativeDestroy(mNative);
}
}
}
static final class StyleIDs {
private int boldId = -1;
private int italicId = -1;
private int underlineId = -1;
private int ttId = -1;
private int bigId = -1;
private int smallId = -1;
private int subId = -1;
private int supId = -1;
private int strikeId = -1;
private int listItemId = -1;
private int marqueeId = -1;
}
private CharSequence applyStyles(String str, int[] style, StyleIDs ids) {
if (style.length == 0)
return str;
SpannableString buffer = new SpannableString(str);
int i=0;
while (i < style.length) {
int type = style[i];
if (localLOGV) Log.v(TAG, "Applying style span id=" + type
+ ", start=" + style[i+1] + ", end=" + style[i+2]);
if (type == ids.boldId) {
buffer.setSpan(new StyleSpan(Typeface.BOLD),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.italicId) {
buffer.setSpan(new StyleSpan(Typeface.ITALIC),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.underlineId) {
buffer.setSpan(new UnderlineSpan(),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.ttId) {
buffer.setSpan(new TypefaceSpan("monospace"),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.bigId) {
buffer.setSpan(new RelativeSizeSpan(1.25f),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.smallId) {
buffer.setSpan(new RelativeSizeSpan(0.8f),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.subId) {
buffer.setSpan(new SubscriptSpan(),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.supId) {
buffer.setSpan(new SuperscriptSpan(),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.strikeId) {
buffer.setSpan(new StrikethroughSpan(),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.listItemId) {
addParagraphSpan(buffer, new BulletSpan(10),
style[i+1], style[i+2]+1);
} else if (type == ids.marqueeId) {
buffer.setSpan(TextUtils.TruncateAt.MARQUEE,
style[i+1], style[i+2]+1,
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
} else {
String tag = nativeGetString(mNative, type);
if (tag.startsWith("font;")) {
String sub;
sub = subtag(tag, ";height=");
if (sub != null) {
int size = Integer.parseInt(sub);
addParagraphSpan(buffer, new Height(size),
style[i+1], style[i+2]+1);
}
sub = subtag(tag, ";size=");
if (sub != null) {
int size = Integer.parseInt(sub);
buffer.setSpan(new AbsoluteSizeSpan(size, true),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
sub = subtag(tag, ";fgcolor=");
if (sub != null) {
buffer.setSpan(getColor(sub, true),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
sub = subtag(tag, ";color=");
if (sub != null) {
buffer.setSpan(getColor(sub, true),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
sub = subtag(tag, ";bgcolor=");
if (sub != null) {
buffer.setSpan(getColor(sub, false),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
sub = subtag(tag, ";face=");
if (sub != null) {
buffer.setSpan(new TypefaceSpan(sub),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else if (tag.startsWith("a;")) {
String sub;
sub = subtag(tag, ";href=");
if (sub != null) {
buffer.setSpan(new URLSpan(sub),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else if (tag.startsWith("annotation;")) {
int len = tag.length();
int next;
for (int t = tag.indexOf(';'); t < len; t = next) {
int eq = tag.indexOf('=', t);
if (eq < 0) {
break;
}
next = tag.indexOf(';', eq);
if (next < 0) {
next = len;
}
String key = tag.substring(t + 1, eq);
String value = tag.substring(eq + 1, next);
buffer.setSpan(new Annotation(key, value),
style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
i += 3;
}
return new SpannedString(buffer);
}
/**
* Returns a span for the specified color string representation.
* If the specified string does not represent a color (null, empty, etc.)
* the color black is returned instead.
*
* @param color The color as a string. Can be a resource reference,
* HTML hexadecimal, octal or a name
* @param foreground True if the color will be used as the foreground color,
* false otherwise
*
* @return A CharacterStyle
*
* @see Color#getHtmlColor(String)
* /
private static CharacterStyle getColor(String color, boolean foreground) {
int c = 0xff000000;
if (!TextUtils.isEmpty(color)) {
if (color.startsWith("@")) {
Resources res = Resources.getSystem();
String name = color.substring(1);
int colorRes = res.getIdentifier(name, "color", "android");
if (colorRes != 0) {
ColorStateList colors = res.getColorStateList(colorRes);
if (foreground) {
return new TextAppearanceSpan(null, 0, 0, colors, null);
} else {
c = colors.getDefaultColor();
}
}
} else {
c = Color.getHtmlColor(color);
}
}
if (foreground) {
return new ForegroundColorSpan(c);
} else {
return new BackgroundColorSpan(c);
}
}
/**
* If a translator has messed up the edges of paragraph-level markup,
* fix it to actually cover the entire paragraph that it is attached to
* instead of just whatever range they put it on.
* /
private static void addParagraphSpan(Spannable buffer, Object what,
int start, int end) {
int len = buffer.length();
if (start != 0 && start != len && buffer.charAt(start - 1) != '\n') {
for (start--; start > 0; start--) {
if (buffer.charAt(start - 1) == '\n') {
break;
}
}
}
if (end != 0 && end != len && buffer.charAt(end - 1) != '\n') {
for (end++; end < len; end++) {
if (buffer.charAt(end - 1) == '\n') {
break;
}
}
}
buffer.setSpan(what, start, end, Spannable.SPAN_PARAGRAPH);
}
private static String subtag(String full, String attribute) {
int start = full.indexOf(attribute);
if (start < 0) {
return null;
}
start += attribute.length();
int end = full.indexOf(';', start);
if (end < 0) {
return full.substring(start);
} else {
return full.substring(start, end);
}
}
/**
* Forces the text line to be the specified height, shrinking/stretching
* the ascent if possible, or the descent if shrinking the ascent further
* will make the text unreadable.
* /
private static class Height implements LineHeightSpan.WithDensity {
private int mSize;
private static float sProportion = 0;
public Height(int size) {
mSize = size;
}
public void chooseHeight(CharSequence text, int start, int end,
int spanstartv, int v,
Paint.FontMetricsInt fm) {
// Should not get called, at least not by StaticLayout.
chooseHeight(text, start, end, spanstartv, v, fm, null);
}
public void chooseHeight(CharSequence text, int start, int end,
int spanstartv, int v,
Paint.FontMetricsInt fm, TextPaint paint) {
int size = mSize;
if (paint != null) {
size *= paint.density;
}
if (fm.bottom - fm.top < size) {
fm.top = fm.bottom - size;
fm.ascent = fm.ascent - size;
} else {
if (sProportion == 0) {
/*
* Calculate what fraction of the nominal ascent
* the height of a capital letter actually is,
* so that we won't reduce the ascent to less than
* that unless we absolutely have to.
* /
Paint p = new Paint();
p.setTextSize(100);
Rect r = new Rect();
p.getTextBounds("ABCDEFG", 0, 7, r);
sProportion = (r.top) / p.ascent();
}
int need = (int) Math.ceil(-fm.top * sProportion);
if (size - fm.descent >= need) {
/*
* It is safe to shrink the ascent this much.
* /
fm.top = fm.bottom - size;
fm.ascent = fm.descent - size;
} else if (size >= need) {
/*
* We can't show all the descent, but we can at least
* show all the ascent.
* /
fm.top = fm.ascent = -need;
fm.bottom = fm.descent = fm.top + size;
} else {
/*
* Show as much of the ascent as we can, and no descent.
* /
fm.top = fm.ascent = -size;
fm.bottom = fm.descent = 0;
}
}
}
}
*/
/**
* Create from an existing string block native object. This is
* -extremely- dangerous -- only use it if you absolutely know what you
* are doing! The given native object must exist for the entire lifetime
* of this newly creating StringBlock.
*/
StringBlock(int obj, boolean useSparse) {
mNative = obj;
mUseSparse = useSparse;
mOwnsNative = false;
if (localLOGV) Log.v(TAG, "Created string block " + this
+ ": " + nativeGetSize(mNative));
}
private static native int nativeCreate(byte[] data,
int offset,
int size);
private static native int nativeGetSize(int obj);
private static native String nativeGetString(int obj, int idx);
private static native int[] nativeGetStyle(int obj, int idx);
private static native void nativeDestroy(int obj);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2006 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.content.res;
import org.xmlpull.v1.XmlPullParser;
import android.util.AttributeSet;
/**
* The XML parsing interface returned for an XML resource. This is a standard
* XmlPullParser interface, as well as an extended AttributeSet interface and
* an additional close() method on this interface for the client to indicate
* when it is done reading the resource.
*/
public interface XmlResourceParser extends XmlPullParser, AttributeSet, AutoCloseable {
/**
* Close this interface to the resource. Calls on the interface are no
* longer value after this call.
*/
public void close();
}