LayoutLib fixes for N

Moves LayoutLib to Java 8 - YAY!
Fix delegates

Change-Id: I098996e43e330e995d33f12df1c16355bbc02f0f
This commit is contained in:
Deepanshu Gupta
2015-10-06 17:56:37 -07:00
parent be8c223c24
commit 491523d52c
24 changed files with 1139 additions and 362 deletions

View File

@ -69,10 +69,8 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
private static final int[] ATTRS_TEXT_COLOR = new int[] {R.attr.textColor};
private static final int[] ATTRS_DISABLED_ALPHA = new int[] {R.attr.disabledAlpha};
// LayoutLib relies on these constants. Change TimePickerClockDelegate_Delegate if
// modifying these.
static final int AM = 0;
static final int PM = 1;
private static final int AM = 0;
private static final int PM = 1;
private static final int HOURS_IN_HALF_DAY = 12;

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="InspectionProjectProfileManager">
<profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" />
@ -8,6 +7,15 @@
<option name="CHECK_TRY_CATCH_SECTION" value="true" />
<option name="CHECK_METHOD_BODY" value="true" />
</inspection_tool>
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
</inspection_tool>
<inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
<option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="false" />
<option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="false" />
<option name="SUGGEST_PRIVATE_FOR_INNERS" value="true" />
</inspection_tool>
</profile>
</component>

View File

@ -37,7 +37,7 @@
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -26,4 +26,4 @@
<ConfigurationWrapper RunnerId="Run" />
<method />
</configuration>
</component>
</component>

View File

@ -16,8 +16,6 @@
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_JAVACFLAGS := -source 6 -target 6
#
# Define rules to build temp_layoutlib.jar, which contains a subset of
# the classes in framework.jar. The layoutlib_create tool is used to

View File

@ -18,8 +18,6 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_JAVA_RESOURCE_DIRS := resources
LOCAL_JAVACFLAGS := -source 6 -target 6
LOCAL_JAVA_LIBRARIES := \
layoutlib_api-prebuilt \

View File

@ -49,6 +49,7 @@ import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Iterator;
@SuppressWarnings("deprecation")
public final class BridgeResources extends Resources {
private BridgeContext mContext;
@ -70,6 +71,7 @@ public final class BridgeResources extends Resources {
@Override
public boolean markSupported() {
//noinspection SimplifiableIfStatement
if (mFakeMarkSupport) {
// this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream.
return true;
@ -595,7 +597,6 @@ public final class BridgeResources extends Resources {
if (value != null) {
ResourceValue resValue = value.getSecond();
assert resValue != null;
if (resValue != null) {
String v = resValue.getValue();
if (v != null) {

View File

@ -17,9 +17,14 @@
package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.resources.Density;
import com.android.resources.ResourceType;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.Nullable;
@ -38,6 +43,7 @@ import java.util.EnumSet;
import java.util.Set;
import javax.imageio.ImageIO;
import libcore.util.NativeAllocationRegistry_Delegate;
/**
* Delegate implementing the native methods of android.graphics.Bitmap
@ -62,12 +68,13 @@ public final class Bitmap_Delegate {
// ---- delegate manager ----
private static final DelegateManager<Bitmap_Delegate> sManager =
new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class);
private static long sFinalizer = -1;
// ---- delegate helper data ----
// ---- delegate data ----
private final Config mConfig;
private BufferedImage mImage;
private final BufferedImage mImage;
private boolean mHasAlpha = true;
private boolean mHasMipMap = false; // TODO: check the default.
private boolean mIsPremultiplied = true;
@ -114,10 +121,25 @@ public final class Bitmap_Delegate {
* @see Bitmap#isMutable()
* @see Bitmap#getDensity()
*/
public static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
private static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
Density density) throws IOException {
// create a delegate with the content of the file.
Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
BufferedImage image = ImageIO.read(input);
if (image == null && input.exists()) {
// There was a problem decoding the image, or the decoder isn't registered. Webp maybe.
// Replace with a broken image icon.
BridgeContext currentContext = RenderAction.getCurrentContext();
if (currentContext != null) {
RenderResources resources = currentContext.getRenderResources();
ResourceValue broken = resources.getFrameworkResource(ResourceType.DRAWABLE,
"ic_menu_report_image");
File brokenFile = new File(broken.getValue());
if (brokenFile.exists()) {
image = ImageIO.read(brokenFile);
}
}
}
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
return createBitmap(delegate, createFlags, density.getDpiValue());
}
@ -281,8 +303,13 @@ public final class Bitmap_Delegate {
}
@LayoutlibDelegate
/*package*/ static void nativeDestructor(long nativeBitmap) {
sManager.removeJavaReferenceFor(nativeBitmap);
/*package*/ static long nativeGetNativeFinalizer() {
synchronized (Bitmap_Delegate.class) {
if (sFinalizer == -1) {
sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
}
return sFinalizer;
}
}
@LayoutlibDelegate

View File

@ -21,6 +21,7 @@ import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.GcSnapshot;
import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.ninepatch.NinePatchChunk;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.Nullable;
@ -38,6 +39,8 @@ import java.awt.geom.Arc2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import libcore.util.NativeAllocationRegistry_Delegate;
/**
* Delegate implementing the native methods of android.graphics.Canvas
@ -57,6 +60,7 @@ public final class Canvas_Delegate {
// ---- delegate manager ----
private static final DelegateManager<Canvas_Delegate> sManager =
new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class);
private static long sFinalizer = -1;
// ---- delegate helper data ----
@ -159,6 +163,9 @@ public final class Canvas_Delegate {
return canvasDelegate.mBitmap.getConfig() == Config.RGB_565;
}
@LayoutlibDelegate
/*package*/ static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
@LayoutlibDelegate
/*package*/ static int native_getWidth(long nativeCanvas) {
// get the delegate from the native int.
@ -748,6 +755,61 @@ public final class Canvas_Delegate {
});
}
@LayoutlibDelegate
/*package*/ static void native_drawRegion(long nativeCanvas, long nativeRegion,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Some canvas paths may not be drawn", null, null);
}
@LayoutlibDelegate
/*package*/ static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop,
final float dstRight, final float dstBottom, long nativePaintOrZero,
final int screenDensity, final int bitmapDensity) {
// get the delegate from the native int.
final Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmap);
if (bitmapDelegate == null) {
return;
}
byte[] c = NinePatch_Delegate.getChunk(ninePatch);
if (c == null) {
// not a 9-patch?
BufferedImage image = bitmapDelegate.getImage();
drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 0, 0, image.getWidth(),
image.getHeight(), (int) dstLeft, (int) dstTop, (int) dstRight,
(int) dstBottom);
return;
}
final NinePatchChunk chunkObject = NinePatch_Delegate.getChunk(c);
assert chunkObject != null;
if (chunkObject == null) {
return;
}
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
// this one can be null
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paint) {
chunkObject.draw(bitmapDelegate.getImage(), graphics, (int) dstLeft, (int) dstTop,
(int) (dstRight - dstLeft), (int) (dstBottom - dstTop), screenDensity,
bitmapDensity);
}
}, paintDelegate, true, false);
}
@LayoutlibDelegate
/*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float left, float top,
@ -934,20 +996,21 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
/*package*/ static void finalizer(long nativeCanvas) {
// get the delegate from the native int so that it can be disposed.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
/*package*/ static long getNativeFinalizer() {
synchronized (Canvas_Delegate.class) {
if (sFinalizer == -1) {
sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(nativePtr -> {
Canvas_Delegate delegate = sManager.getDelegate(nativePtr);
if (delegate != null) {
delegate.dispose();
}
sManager.removeJavaReferenceFor(nativePtr);
});
}
}
canvasDelegate.dispose();
// remove it from the manager.
sManager.removeJavaReferenceFor(nativeCanvas);
return sFinalizer;
}
// ---- Private delegate/helper methods ----
/**

View File

@ -33,13 +33,13 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
@ -213,7 +213,7 @@ public class FontFamily_Delegate {
return mValid;
}
/*package*/ static Font loadFont(String path) {
private static Font loadFont(String path) {
if (path.startsWith(SYSTEM_FONTS) ) {
String relativePath = path.substring(SYSTEM_FONTS.length());
File f = new File(sFontLocation, relativePath);
@ -270,16 +270,12 @@ public class FontFamily_Delegate {
}
@LayoutlibDelegate
/*package*/ static boolean nAddFont(long nativeFamily, final String path) {
/*package*/ static boolean nAddFont(long nativeFamily, final String path, int ttcIndex) {
// FIXME: support ttc fonts. Hack JRE??
final FontFamily_Delegate delegate = getDelegate(nativeFamily);
if (delegate != null) {
if (sFontLocation == null) {
delegate.mPostInitRunnables.add(new Runnable() {
@Override
public void run() {
delegate.addFont(path);
}
});
delegate.mPostInitRunnables.add(() -> delegate.addFont(path));
return true;
}
return delegate.addFont(path);
@ -289,18 +285,18 @@ public class FontFamily_Delegate {
@LayoutlibDelegate
/*package*/ static boolean nAddFontWeightStyle(long nativeFamily,
final String path, final int index, final List<FontListParser.Axis> axes,
ByteBuffer buffer, final List<FontListParser.Axis> axes,
final int weight, final boolean isItalic) {
// 'index' and 'axes' are not supported by java.awt.Font
assert false : "The only client of this method has been overriden.";
return false;
}
static boolean addFont(long nativeFamily, final String path, final int weight,
final boolean isItalic) {
final FontFamily_Delegate delegate = getDelegate(nativeFamily);
if (delegate != null) {
if (sFontLocation == null) {
delegate.mPostInitRunnables.add(new Runnable() {
@Override
public void run() {
delegate.addFont(path, weight, isItalic);
}
});
delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, isItalic));
return true;
}
return delegate.addFont(path, weight, isItalic);
@ -311,6 +307,9 @@ public class FontFamily_Delegate {
@LayoutlibDelegate
/*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily);
if (ffd == null) {
return false;
}
ffd.mValid = true;
if (mgr == null) {
return false;
@ -454,6 +453,7 @@ public class FontFamily_Delegate {
private FontInfo deriveFont(@NonNull FontInfo srcFont, @NonNull FontInfo outFont) {
int desiredWeight = outFont.mWeight;
int srcWeight = srcFont.mWeight;
assert srcFont.mFont != null;
Font derivedFont = srcFont.mFont;
// Embolden the font if required.
if (desiredWeight >= BOLD_FONT_WEIGHT && desiredWeight - srcWeight > BOLD_FONT_WEIGHT_DELTA / 2) {

View File

@ -169,77 +169,18 @@ public final class NinePatch_Delegate {
sManager.removeJavaReferenceFor(chunk);
}
@LayoutlibDelegate
/*package*/ static void nativeDraw(long canvas_instance, RectF loc, Bitmap bitmap_instance,
long chunk, long paint_instance_or_null, int destDensity, int srcDensity) {
draw(canvas_instance,
(int) loc.left, (int) loc.top, (int) loc.right, (int) loc.bottom,
bitmap_instance, chunk, paint_instance_or_null,
destDensity, srcDensity);
}
@LayoutlibDelegate
/*package*/ static void nativeDraw(long canvas_instance, Rect loc, Bitmap bitmap_instance,
long chunk, long paint_instance_or_null, int destDensity, int srcDensity) {
draw(canvas_instance,
loc.left, loc.top, loc.right, loc.bottom,
bitmap_instance, chunk, paint_instance_or_null,
destDensity, srcDensity);
}
@LayoutlibDelegate
/*package*/ static long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location) {
return 0;
}
// ---- Private Helper methods ----
private static void draw(long canvas_instance,
final int left, final int top, final int right, final int bottom,
Bitmap bitmap_instance, long chunk, long paint_instance_or_null,
final int destDensity, final int srcDensity) {
// get the delegate from the native int.
final Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance);
if (bitmap_delegate == null) {
return;
}
byte[] c = null;
NinePatch_Delegate delegate = sManager.getDelegate(chunk);
static byte[] getChunk(long nativeNinePatch) {
NinePatch_Delegate delegate = sManager.getDelegate(nativeNinePatch);
if (delegate != null) {
c = delegate.chunk;
}
if (c == null) {
// not a 9-patch?
BufferedImage image = bitmap_delegate.getImage();
Canvas_Delegate.native_drawBitmap(null, canvas_instance, bitmap_instance,
0f, 0f, (float)image.getWidth(), (float)image.getHeight(),
(float)left, (float)top, (float)right, (float)bottom,
paint_instance_or_null, destDensity, srcDensity);
return;
return delegate.chunk;
}
return null;
}
final NinePatchChunk chunkObject = getChunk(c);
assert chunkObject != null;
if (chunkObject == null) {
return;
}
Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance);
if (canvas_delegate == null) {
return;
}
// this one can be null
Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null);
canvas_delegate.getSnapshot().draw(new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paint) {
chunkObject.draw(bitmap_delegate.getImage(), graphics,
left, top, right - left, bottom - top, destDensity, srcDensity);
}
}, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/);
}
}

View File

@ -39,6 +39,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import libcore.util.NativeAllocationRegistry_Delegate;
/**
* Delegate implementing the native methods of android.graphics.Paint
*
@ -65,6 +67,7 @@ public class Paint_Delegate {
// ---- delegate manager ----
private static final DelegateManager<Paint_Delegate> sManager =
new DelegateManager<Paint_Delegate>(Paint_Delegate.class);
private static long sFinalizer = -1;
// ---- delegate helper data ----
@ -250,9 +253,9 @@ public class Paint_Delegate {
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static int getFlags(Paint thisPaint) {
/*package*/ static int nGetFlags(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@ -263,9 +266,9 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setFlags(Paint thisPaint, int flags) {
/*package*/ static void nSetFlags(Paint thisPaint, long nativePaint, int flags) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -274,14 +277,14 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) {
setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter);
/*package*/ static void nSetFilterBitmap(Paint thisPaint, long nativePaint, boolean filter) {
setFlag(nativePaint, Paint.FILTER_BITMAP_FLAG, filter);
}
@LayoutlibDelegate
/*package*/ static int getHinting(Paint thisPaint) {
/*package*/ static int nGetHinting(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return Paint.HINTING_ON;
}
@ -290,9 +293,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setHinting(Paint thisPaint, int mode) {
/*package*/ static void nSetHinting(Paint thisPaint, long nativePaint, int mode) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -301,44 +304,48 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) {
setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa);
/*package*/ static void nSetAntiAlias(Paint thisPaint, long nativePaint, boolean aa) {
setFlag(nativePaint, Paint.ANTI_ALIAS_FLAG, aa);
}
@LayoutlibDelegate
/*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) {
setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
/*package*/ static void nSetSubpixelText(Paint thisPaint, long nativePaint,
boolean subpixelText) {
setFlag(nativePaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
}
@LayoutlibDelegate
/*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) {
setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
/*package*/ static void nSetUnderlineText(Paint thisPaint, long nativePaint,
boolean underlineText) {
setFlag(nativePaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
}
@LayoutlibDelegate
/*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) {
setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
/*package*/ static void nSetStrikeThruText(Paint thisPaint, long nativePaint,
boolean strikeThruText) {
setFlag(nativePaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
}
@LayoutlibDelegate
/*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) {
setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
/*package*/ static void nSetFakeBoldText(Paint thisPaint, long nativePaint,
boolean fakeBoldText) {
setFlag(nativePaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
}
@LayoutlibDelegate
/*package*/ static void setDither(Paint thisPaint, boolean dither) {
setFlag(thisPaint, Paint.DITHER_FLAG, dither);
/*package*/ static void nSetDither(Paint thisPaint, long nativePaint, boolean dither) {
setFlag(nativePaint, Paint.DITHER_FLAG, dither);
}
@LayoutlibDelegate
/*package*/ static void setLinearText(Paint thisPaint, boolean linearText) {
setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText);
/*package*/ static void nSetLinearText(Paint thisPaint, long nativePaint, boolean linearText) {
setFlag(nativePaint, Paint.LINEAR_TEXT_FLAG, linearText);
}
@LayoutlibDelegate
/*package*/ static int getColor(Paint thisPaint) {
/*package*/ static int nGetColor(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@ -347,9 +354,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setColor(Paint thisPaint, int color) {
/*package*/ static void nSetColor(Paint thisPaint, long nativePaint, int color) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -358,9 +365,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int getAlpha(Paint thisPaint) {
/*package*/ static int nGetAlpha(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@ -369,9 +376,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setAlpha(Paint thisPaint, int a) {
/*package*/ static void nSetAlpha(Paint thisPaint, long nativePaint, int a) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -380,9 +387,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float getStrokeWidth(Paint thisPaint) {
/*package*/ static float nGetStrokeWidth(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@ -391,9 +398,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setStrokeWidth(Paint thisPaint, float width) {
/*package*/ static void nSetStrokeWidth(Paint thisPaint, long nativePaint, float width) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -402,9 +409,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float getStrokeMiter(Paint thisPaint) {
/*package*/ static float nGetStrokeMiter(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@ -413,9 +420,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setStrokeMiter(Paint thisPaint, float miter) {
/*package*/ static void nSetStrokeMiter(Paint thisPaint, long nativePaint, float miter) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -424,7 +431,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setShadowLayer(long paint, float radius, float dx, float dy,
/*package*/ static void nSetShadowLayer(long paint, float radius, float dx, float dy,
int color) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@ -432,7 +439,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static boolean native_hasShadowLayer(long paint) {
/*package*/ static boolean nHasShadowLayer(long paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Paint.hasShadowLayer is not supported.", null, null /*data*/);
@ -440,16 +447,17 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
/*package*/ static boolean nIsElegantTextHeight(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT;
}
@LayoutlibDelegate
/*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) {
/*package*/ static void nSetElegantTextHeight(Paint thisPaint, long nativePaint,
boolean elegant) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -458,9 +466,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float getTextSize(Paint thisPaint) {
/*package*/ static float nGetTextSize(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@ -469,9 +477,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setTextSize(Paint thisPaint, float textSize) {
/*package*/ static void nSetTextSize(Paint thisPaint, long nativePaint, float textSize) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -483,9 +491,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float getTextScaleX(Paint thisPaint) {
/*package*/ static float nGetTextScaleX(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@ -494,9 +502,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) {
/*package*/ static void nSetTextScaleX(Paint thisPaint, long nativePaint, float scaleX) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -508,9 +516,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float getTextSkewX(Paint thisPaint) {
/*package*/ static float nGetTextSkewX(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@ -519,9 +527,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void setTextSkewX(Paint thisPaint, float skewX) {
/*package*/ static void nSetTextSkewX(Paint thisPaint, long nativePaint, float skewX) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@ -533,9 +541,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float ascent(Paint thisPaint) {
/*package*/ static float nAscent(Paint thisPaint, long nativePaint, long nativeTypeface) {
// get the delegate
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@ -550,9 +558,9 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float descent(Paint thisPaint) {
/*package*/ static float nDescent(Paint thisPaint, long nativePaint, long nativeTypeface) {
// get the delegate
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@ -567,9 +575,10 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
/*package*/ static float nGetFontMetrics(Paint thisPaint, long nativePaint, long nativeTypeface,
FontMetrics metrics) {
// get the delegate
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@ -578,9 +587,10 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
/*package*/ static int nGetFontMetricsInt(Paint thisPaint, long nativePaint,
long nativeTypeface, FontMetricsInt fmi) {
// get the delegate
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@ -603,31 +613,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
int count, int bidiFlags) {
// get the delegate
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
RectF bounds = delegate.measureText(text, index, count, null, 0, bidiFlags);
return bounds.right - bounds.left;
}
@LayoutlibDelegate
/*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end,
int bidiFlags) {
return native_measureText(thisPaint, text.toCharArray(), start, end - start, bidiFlags);
}
@LayoutlibDelegate
/*package*/ static float native_measureText(Paint thisPaint, String text, int bidiFlags) {
return native_measureText(thisPaint, text.toCharArray(), 0, text.length(), bidiFlags);
}
@LayoutlibDelegate
/*package*/ static int native_breakText(long nativePaint, long nativeTypeface, char[] text,
/*package*/ static int nBreakText(long nativePaint, long nativeTypeface, char[] text,
int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) {
// get the delegate
@ -669,21 +655,21 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int native_breakText(long nativePaint, long nativeTypeface, String text,
/*package*/ static int nBreakText(long nativePaint, long nativeTypeface, String text,
boolean measureForwards,
float maxWidth, int bidiFlags, float[] measuredWidth) {
return native_breakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
return nBreakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
maxWidth, bidiFlags, measuredWidth);
}
@LayoutlibDelegate
/*package*/ static long native_init() {
/*package*/ static long nInit() {
Paint_Delegate newDelegate = new Paint_Delegate();
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static long native_initWithPaint(long paint) {
/*package*/ static long nInitWithPaint(long paint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(paint);
if (delegate == null) {
@ -695,7 +681,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_reset(long native_object) {
/*package*/ static void nReset(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -706,7 +692,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_set(long native_dst, long native_src) {
/*package*/ static void nSet(long native_dst, long native_src) {
// get the delegate from the native int.
Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
if (delegate_dst == null) {
@ -723,7 +709,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int native_getStyle(long native_object) {
/*package*/ static int nGetStyle(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -734,7 +720,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setStyle(long native_object, int style) {
/*package*/ static void nSetStyle(long native_object, int style) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -745,7 +731,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int native_getStrokeCap(long native_object) {
/*package*/ static int nGetStrokeCap(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -756,7 +742,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setStrokeCap(long native_object, int cap) {
/*package*/ static void nSetStrokeCap(long native_object, int cap) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -767,7 +753,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int native_getStrokeJoin(long native_object) {
/*package*/ static int nGetStrokeJoin(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -778,7 +764,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setStrokeJoin(long native_object, int join) {
/*package*/ static void nSetStrokeJoin(long native_object, int join) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -789,7 +775,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static boolean native_getFillPath(long native_object, long src, long dst) {
/*package*/ static boolean nGetFillPath(long native_object, long src, long dst) {
Paint_Delegate paint = sManager.getDelegate(native_object);
if (paint == null) {
return false;
@ -815,7 +801,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static long native_setShader(long native_object, long shader) {
/*package*/ static long nSetShader(long native_object, long shader) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -828,7 +814,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static long native_setColorFilter(long native_object, long filter) {
/*package*/ static long nSetColorFilter(long native_object, long filter) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -847,7 +833,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static long native_setXfermode(long native_object, long xfermode) {
/*package*/ static long nSetXfermode(long native_object, long xfermode) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -860,7 +846,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static long native_setPathEffect(long native_object, long effect) {
/*package*/ static long nSetPathEffect(long native_object, long effect) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -873,7 +859,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static long native_setMaskFilter(long native_object, long maskfilter) {
/*package*/ static long nSetMaskFilter(long native_object, long maskfilter) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -892,7 +878,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static long native_setTypeface(long native_object, long typeface) {
/*package*/ static long nSetTypeface(long native_object, long typeface) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -909,7 +895,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static long native_setRasterizer(long native_object, long rasterizer) {
/*package*/ static long nSetRasterizer(long native_object, long rasterizer) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -928,7 +914,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int native_getTextAlign(long native_object) {
/*package*/ static int nGetTextAlign(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -939,7 +925,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setTextAlign(long native_object, int align) {
/*package*/ static void nSetTextAlign(long native_object, int align) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@ -950,58 +936,27 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setTextLocale(long native_object, String locale) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
return;
}
delegate.setTextLocale(locale);
}
@LayoutlibDelegate
/*package*/ static int native_getTextWidths(long native_object, long native_typeface,
char[] text, int index, int count, int bidiFlags, float[] widths) {
if (widths != null) {
for (int i = 0; i< count; i++) {
widths[i]=0;
}
}
/*package*/ static int nSetTextLocales(long native_object, String locale) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
return 0;
}
// native_typeface is passed here since Framework's old implementation did not have the
// typeface object associated with the Paint. Since, we follow the new framework way,
// we store the typeface with the paint and use it directly.
assert (native_typeface == delegate.mNativeTypeface);
RectF bounds = delegate.measureText(text, index, count, widths, 0, bidiFlags);
return ((int) (bounds.right - bounds.left));
}
@LayoutlibDelegate
/*package*/ static int native_getTextWidths(long native_object, long native_typeface,
String text, int start, int end, int bidiFlags, float[] widths) {
return native_getTextWidths(native_object, native_typeface, text.toCharArray(), start,
end - start, bidiFlags, widths);
}
@LayoutlibDelegate
/* package */static int native_getTextGlyphs(long native_object, String text, int start,
int end, int contextStart, int contextEnd, int flags, char[] glyphs) {
// FIXME
delegate.setTextLocale(locale);
return 0;
}
@LayoutlibDelegate
/*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface,
/*package*/ static void nSetTextLocalesByMinikinLangListId(long paintPtr,
int mMinikinLangListId) {
// FIXME
}
@LayoutlibDelegate
/*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
char[] text, int index, int count, int contextIndex, int contextCount,
boolean isRtl, float[] advances, int advancesIndex) {
int bidiFlags, float[] advances, int advancesIndex) {
if (advances != null)
for (int i = advancesIndex; i< advancesIndex+count; i++)
@ -1017,25 +972,25 @@ public class Paint_Delegate {
// we store the typeface with the paint and use it directly.
assert (native_typeface == delegate.mNativeTypeface);
RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, isRtl);
RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, bidiFlags);
return bounds.right - bounds.left;
}
@LayoutlibDelegate
/*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface,
/*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
String text, int start, int end, int contextStart, int contextEnd,
boolean isRtl, float[] advances, int advancesIndex) {
int bidiFlags, float[] advances, int advancesIndex) {
// FIXME: support contextStart and contextEnd
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
return native_getTextRunAdvances(native_object, native_typeface, buffer, 0, count,
contextStart, contextEnd - contextStart, isRtl, advances, advancesIndex);
return nGetTextAdvances(native_object, native_typeface, buffer, 0, count,
contextStart, contextEnd - contextStart, bidiFlags, advances, advancesIndex);
}
@LayoutlibDelegate
/*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, char[] text,
/*package*/ static int nGetTextRunCursor(Paint thisPaint, long native_object, char[] text,
int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@ -1044,7 +999,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, String text,
/*package*/ static int nGetTextRunCursor(Paint thisPaint, long native_object, String text,
int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@ -1053,7 +1008,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_getTextPath(long native_object, long native_typeface,
/*package*/ static void nGetTextPath(long native_object, long native_typeface,
int bidiFlags, char[] text, int index, int count, float x, float y, long path) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@ -1061,7 +1016,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_getTextPath(long native_object, long native_typeface,
/*package*/ static void nGetTextPath(long native_object, long native_typeface,
int bidiFlags, String text, int start, int end, float x, float y, long path) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@ -1069,14 +1024,14 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void nativeGetStringBounds(long nativePaint, long native_typeface,
/*package*/ static void nGetStringBounds(long nativePaint, long native_typeface,
String text, int start, int end, int bidiFlags, Rect bounds) {
nativeGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
nGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
end - start, bidiFlags, bounds);
}
@LayoutlibDelegate
/*package*/ static void nativeGetCharArrayBounds(long nativePaint, long native_typeface,
/*package*/ static void nGetCharArrayBounds(long nativePaint, long native_typeface,
char[] text, int index, int count, int bidiFlags, Rect bounds) {
// get the delegate from the native int.
@ -1092,12 +1047,18 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void finalizer(long nativePaint) {
sManager.removeJavaReferenceFor(nativePaint);
/*package*/ static long nGetNativeFinalizer() {
synchronized (Paint_Delegate.class) {
if (sFinalizer == -1) {
sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(
sManager::removeJavaReferenceFor);
}
}
return sFinalizer;
}
@LayoutlibDelegate
/*package*/ static float native_getLetterSpacing(long nativePaint) {
/*package*/ static float nGetLetterSpacing(long nativePaint) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
@ -1106,7 +1067,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setLetterSpacing(long nativePaint, float letterSpacing) {
/*package*/ static void nSetLetterSpacing(long nativePaint, float letterSpacing) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
"Paint.setLetterSpacing() not supported.", null, null);
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
@ -1117,13 +1078,13 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setFontFeatureSettings(long nativePaint, String settings) {
/*package*/ static void nSetFontFeatureSettings(long nativePaint, String settings) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
"Paint.setFontFeatureSettings() not supported.", null, null);
}
@LayoutlibDelegate
/*package*/ static int native_getHyphenEdit(long nativePaint) {
/*package*/ static int nGetHyphenEdit(long nativePaint) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
@ -1132,7 +1093,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_setHyphenEdit(long nativePaint, int hyphen) {
/*package*/ static void nSetHyphenEdit(long nativePaint, int hyphen) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
@ -1141,7 +1102,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static boolean native_hasGlyph(long nativePaint, long nativeTypeface, int bidiFlags,
/*package*/ static boolean nHasGlyph(long nativePaint, long nativeTypeface, int bidiFlags,
String string) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
@ -1169,13 +1130,14 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float native_getRunAdvance(long nativePaint, long nativeTypeface,
/*package*/ static float nGetRunAdvance(long nativePaint, long nativeTypeface,
@NonNull char[] text, int start, int end, int contextStart, int contextEnd,
boolean isRtl, int offset) {
int count = end - start;
float[] advances = new float[count];
native_getTextRunAdvances(nativePaint, nativeTypeface, text, start, count,
contextStart, contextEnd - contextStart, isRtl, advances, 0);
int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
int startOffset = offset - start; // offset from start.
float sum = 0;
for (int i = 0; i < startOffset; i++) {
@ -1185,13 +1147,14 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int native_getOffsetForAdvance(long nativePaint, long nativeTypeface,
/*package*/ static int nGetOffsetForAdvance(long nativePaint, long nativeTypeface,
char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl,
float advance) {
int count = end - start;
float[] advances = new float[count];
native_getTextRunAdvances(nativePaint, nativeTypeface, text, start, count,
contextStart, contextEnd - contextStart, isRtl, advances, 0);
int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
float sum = 0;
int i;
for (i = 0; i < count && sum < advance; i++) {
@ -1359,9 +1322,9 @@ public class Paint_Delegate {
mLocale = new Locale(locale);
}
private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
private static void setFlag(long nativePaint, int flagMask, boolean flagValue) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}

View File

@ -75,7 +75,7 @@ public final class Path_Delegate {
return sManager.getDelegate(nPath);
}
public Shape getJavaShape() {
public Path2D getJavaShape() {
return mPath;
}

View File

@ -24,8 +24,10 @@ import android.graphics.FontFamily_Delegate.FontVariant;
import java.awt.Font;
import java.io.File;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static android.graphics.FontFamily_Delegate.getFontLocation;
@ -205,6 +207,17 @@ public final class Typeface_Delegate {
return new File(getFontLocation());
}
@LayoutlibDelegate
/*package*/ static FontFamily makeFamilyFromParsed(FontListParser.Family family,
Map<String, ByteBuffer> bufferForPath) {
FontFamily fontFamily = new FontFamily(family.lang, family.variant);
for (FontListParser.Font font : family.fonts) {
FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.fontName, font.weight,
font.isItalic);
}
return fontFamily;
}
// ---- Private delegate/helper methods ----
private Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style) {

View File

@ -25,7 +25,7 @@ import java.nio.ByteBuffer;
/**
* Delegate that overrides implementation for certain methods in {@link android.text.Hyphenator}
* <p/>
* Through the layoutlib_create tool, selected methods of StaticLayout have been replaced
* Through the layoutlib_create tool, selected methods of Hyphenator have been replaced
* by calls to methods of the same name in this delegate class.
*/
public class Hyphenator_Delegate {
@ -39,7 +39,8 @@ public class Hyphenator_Delegate {
return null;
}
/*package*/ static long loadHyphenator(ByteBuffer buf, int offset) {
/*package*/ @SuppressWarnings("UnusedParameters") // TODO implement this.
static long loadHyphenator(ByteBuffer buffer, int offset) {
return sDelegateManager.addNewDelegate(new Hyphenator_Delegate());
}
}

View File

@ -0,0 +1,757 @@
/*
* Copyright (C) 2015 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;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.NonNull;
import android.graphics.Path_Delegate;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Delegate that provides implementation for native methods in {@link android.util.PathParser}
* <p/>
* Through the layoutlib_create tool, selected methods of PathParser have been replaced by calls to
* methods of the same name in this delegate class.
*
* Most of the code has been taken from the implementation in
* {@code tools/base/sdk-common/src/main/java/com/android/ide/common/vectordrawable/PathParser.java}
* revision be6fe89a3b686db5a75e7e692a148699973957f3
*/
public class PathParser_Delegate {
private static final Logger LOGGER = Logger.getLogger("PathParser");
// ---- Builder delegate manager ----
private static final DelegateManager<PathParser_Delegate> sManager =
new DelegateManager<PathParser_Delegate>(PathParser_Delegate.class);
// ---- delegate data ----
@NonNull
private PathDataNode[] mPathDataNodes;
private PathParser_Delegate(@NonNull PathDataNode[] nodes) {
mPathDataNodes = nodes;
}
@LayoutlibDelegate
/*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int
stringLength) {
Path_Delegate path_delegate = Path_Delegate.getDelegate(pathPtr);
if (path_delegate == null) {
return false;
}
assert pathString.length() == stringLength;
PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate.getJavaShape());
return true;
}
@LayoutlibDelegate
/*package*/ static void nCreatePathFromPathData(long outPathPtr, long pathData) {
Path_Delegate path_delegate = Path_Delegate.getDelegate(outPathPtr);
PathParser_Delegate source = sManager.getDelegate(outPathPtr);
if (source == null || path_delegate == null) {
return;
}
PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate.getJavaShape());
}
@LayoutlibDelegate
/*package*/ static long nCreateEmptyPathData() {
PathParser_Delegate newDelegate = new PathParser_Delegate(new PathDataNode[0]);
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static long nCreatePathData(long nativePtr) {
PathParser_Delegate source = sManager.getDelegate(nativePtr);
if (source == null) {
return 0;
}
PathParser_Delegate dest = new PathParser_Delegate(deepCopyNodes(source.mPathDataNodes));
return sManager.addNewDelegate(dest);
}
@LayoutlibDelegate
/*package*/ static long nCreatePathDataFromString(@NonNull String pathString,
int stringLength) {
assert pathString.length() == stringLength : "Inconsistent path string length.";
PathDataNode[] nodes = createNodesFromPathData(pathString);
PathParser_Delegate delegate = new PathParser_Delegate(nodes);
return sManager.addNewDelegate(delegate);
}
@LayoutlibDelegate
/*package*/ static boolean nInterpolatePathData(long outDataPtr, long fromDataPtr,
long toDataPtr, float fraction) {
PathParser_Delegate out = sManager.getDelegate(outDataPtr);
PathParser_Delegate from = sManager.getDelegate(fromDataPtr);
PathParser_Delegate to = sManager.getDelegate(toDataPtr);
if (out == null || from == null || to == null) {
return false;
}
int length = from.mPathDataNodes.length;
if (length != to.mPathDataNodes.length) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
"Cannot interpolate path data with different lengths (from " + length + " to " +
to.mPathDataNodes.length + ").", null);
return false;
}
if (out.mPathDataNodes.length != length) {
out.mPathDataNodes = new PathDataNode[length];
}
for (int i = 0; i < length; i++) {
out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i],
to.mPathDataNodes[i], fraction);
}
return true;
}
@LayoutlibDelegate
/*package*/ static void nFinalize(long nativePtr) {
sManager.removeJavaReferenceFor(nativePtr);
}
@LayoutlibDelegate
/*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "morphing path data isn't " +
"supported", null, null);
return false;
}
@LayoutlibDelegate
/*package*/ static void nSetPathData(long outDataPtr, long fromDataPtr) {
PathParser_Delegate out = sManager.getDelegate(outDataPtr);
PathParser_Delegate from = sManager.getDelegate(fromDataPtr);
if (from == null || out == null) {
return;
}
out.mPathDataNodes = deepCopyNodes(from.mPathDataNodes);
}
/**
* @param pathData The string representing a path, the same as "d" string in svg file.
*
* @return an array of the PathDataNode.
*/
@NonNull
private static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
int start = 0;
int end = 1;
ArrayList<PathDataNode> list = new ArrayList<PathDataNode>();
while (end < pathData.length()) {
end = nextStart(pathData, end);
String s = pathData.substring(start, end).trim();
if (s.length() > 0) {
float[] val = getFloats(s);
addNode(list, s.charAt(0), val);
}
start = end;
end++;
}
if ((end - start) == 1 && start < pathData.length()) {
addNode(list, pathData.charAt(start), new float[0]);
}
return list.toArray(new PathDataNode[list.size()]);
}
/**
* @param source The array of PathDataNode to be duplicated.
*
* @return a deep copy of the <code>source</code>.
*/
@NonNull
private static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
PathDataNode[] copy = new PathDataNode[source.length];
for (int i = 0; i < source.length; i++) {
copy[i] = new PathDataNode(source[i]);
}
return copy;
}
private static int nextStart(@NonNull String s, int end) {
char c;
while (end < s.length()) {
c = s.charAt(end);
// Note that 'e' or 'E' are not valid path commands, but could be
// used for floating point numbers' scientific notation.
// Therefore, when searching for next command, we should ignore 'e'
// and 'E'.
if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
&& c != 'e' && c != 'E') {
return end;
}
end++;
}
return end;
}
/**
* Calculate the position of the next comma or space or negative sign
*
* @param s the string to search
* @param start the position to start searching
* @param result the result of the extraction, including the position of the the starting
* position of next number, whether it is ending with a '-'.
*/
private static void extract(@NonNull String s, int start, @NonNull ExtractFloatResult result) {
// Now looking for ' ', ',', '.' or '-' from the start.
int currentIndex = start;
boolean foundSeparator = false;
result.mEndWithNegOrDot = false;
boolean secondDot = false;
boolean isExponential = false;
for (; currentIndex < s.length(); currentIndex++) {
boolean isPrevExponential = isExponential;
isExponential = false;
char currentChar = s.charAt(currentIndex);
switch (currentChar) {
case ' ':
case ',':
foundSeparator = true;
break;
case '-':
// The negative sign following a 'e' or 'E' is not a separator.
if (currentIndex != start && !isPrevExponential) {
foundSeparator = true;
result.mEndWithNegOrDot = true;
}
break;
case '.':
if (!secondDot) {
secondDot = true;
} else {
// This is the second dot, and it is considered as a separator.
foundSeparator = true;
result.mEndWithNegOrDot = true;
}
break;
case 'e':
case 'E':
isExponential = true;
break;
}
if (foundSeparator) {
break;
}
}
// When there is nothing found, then we put the end position to the end
// of the string.
result.mEndPosition = currentIndex;
}
/**
* Parse the floats in the string. This is an optimized version of
* parseFloat(s.split(",|\\s"));
*
* @param s the string containing a command and list of floats
*
* @return array of floats
*/
@NonNull
private static float[] getFloats(@NonNull String s) {
if (s.charAt(0) == 'z' || s.charAt(0) == 'Z') {
return new float[0];
}
try {
float[] results = new float[s.length()];
int count = 0;
int startPosition = 1;
int endPosition;
ExtractFloatResult result = new ExtractFloatResult();
int totalLength = s.length();
// The startPosition should always be the first character of the
// current number, and endPosition is the character after the current
// number.
while (startPosition < totalLength) {
extract(s, startPosition, result);
endPosition = result.mEndPosition;
if (startPosition < endPosition) {
results[count++] = Float.parseFloat(
s.substring(startPosition, endPosition));
}
if (result.mEndWithNegOrDot) {
// Keep the '-' or '.' sign with next number.
startPosition = endPosition;
} else {
startPosition = endPosition + 1;
}
}
return Arrays.copyOf(results, count);
} catch (NumberFormatException e) {
throw new RuntimeException("error in parsing \"" + s + "\"", e);
}
}
private static void addNode(@NonNull ArrayList<PathDataNode> list, char cmd,
@NonNull float[] val) {
list.add(new PathDataNode(cmd, val));
}
private static class ExtractFloatResult {
// We need to return the position of the next separator and whether the
// next float starts with a '-' or a '.'.
private int mEndPosition;
private boolean mEndWithNegOrDot;
}
/**
* Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
* PathDataNode can represent the whole "d" attribute.
*/
private static class PathDataNode {
private char mType;
@NonNull
private float[] mParams;
private PathDataNode(char type, @NonNull float[] params) {
mType = type;
mParams = params;
}
public char getType() {
return mType;
}
@NonNull
public float[] getParams() {
return mParams;
}
private PathDataNode(@NonNull PathDataNode n) {
mType = n.mType;
mParams = Arrays.copyOf(n.mParams, n.mParams.length);
}
/**
* Convert an array of PathDataNode to Path.
*
* @param node The source array of PathDataNode.
* @param path The target Path object.
*/
private static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path2D path) {
float[] current = new float[6];
char previousCommand = 'm';
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < node.length; i++) {
addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
previousCommand = node[i].mType;
}
}
/**
* The current PathDataNode will be interpolated between the <code>nodeFrom</code> and
* <code>nodeTo</code> according to the <code>fraction</code>.
*
* @param nodeFrom The start value as a PathDataNode.
* @param nodeTo The end value as a PathDataNode
* @param fraction The fraction to interpolate.
*/
private void interpolatePathDataNode(@NonNull PathDataNode nodeFrom,
@NonNull PathDataNode nodeTo, float fraction) {
for (int i = 0; i < nodeFrom.mParams.length; i++) {
mParams[i] = nodeFrom.mParams[i] * (1 - fraction)
+ nodeTo.mParams[i] * fraction;
}
}
@SuppressWarnings("PointlessArithmeticExpression")
private static void addCommand(@NonNull Path2D path, float[] current, char cmd,
char lastCmd, @NonNull float[] val) {
int incr = 2;
float cx = current[0];
float cy = current[1];
float cpx = current[2];
float cpy = current[3];
float loopX = current[4];
float loopY = current[5];
switch (cmd) {
case 'z':
case 'Z':
path.closePath();
cx = loopX;
cy = loopY;
case 'm':
case 'M':
case 'l':
case 'L':
case 't':
case 'T':
incr = 2;
break;
case 'h':
case 'H':
case 'v':
case 'V':
incr = 1;
break;
case 'c':
case 'C':
incr = 6;
break;
case 's':
case 'S':
case 'q':
case 'Q':
incr = 4;
break;
case 'a':
case 'A':
incr = 7;
}
for (int k = 0; k < val.length; k += incr) {
boolean reflectCtrl;
float tempReflectedX, tempReflectedY;
switch (cmd) {
case 'm':
cx += val[k + 0];
cy += val[k + 1];
if (k > 0) {
// According to the spec, if a moveto is followed by multiple
// pairs of coordinates, the subsequent pairs are treated as
// implicit lineto commands.
path.lineTo(cx, cy);
} else {
path.moveTo(cx, cy);
loopX = cx;
loopY = cy;
}
break;
case 'M':
cx = val[k + 0];
cy = val[k + 1];
if (k > 0) {
// According to the spec, if a moveto is followed by multiple
// pairs of coordinates, the subsequent pairs are treated as
// implicit lineto commands.
path.lineTo(cx, cy);
} else {
path.moveTo(cx, cy);
loopX = cx;
loopY = cy;
}
break;
case 'l':
cx += val[k + 0];
cy += val[k + 1];
path.lineTo(cx, cy);
break;
case 'L':
cx = val[k + 0];
cy = val[k + 1];
path.lineTo(cx, cy);
break;
case 'z':
case 'Z':
path.closePath();
cx = loopX;
cy = loopY;
break;
case 'h':
cx += val[k + 0];
path.lineTo(cx, cy);
break;
case 'H':
path.lineTo(val[k + 0], cy);
cx = val[k + 0];
break;
case 'v':
cy += val[k + 0];
path.lineTo(cx, cy);
break;
case 'V':
path.lineTo(cx, val[k + 0]);
cy = val[k + 0];
break;
case 'c':
path.curveTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
cy + val[k + 3], cx + val[k + 4], cy + val[k + 5]);
cpx = cx + val[k + 2];
cpy = cy + val[k + 3];
cx += val[k + 4];
cy += val[k + 5];
break;
case 'C':
path.curveTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
val[k + 4], val[k + 5]);
cx = val[k + 4];
cy = val[k + 5];
cpx = val[k + 2];
cpy = val[k + 3];
break;
case 's':
reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
lastCmd == 'S');
path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
* cy - cpy : cy, cx + val[k + 0], cy + val[k + 1], cx
+ val[k + 2], cy + val[k + 3]);
cpx = cx + val[k + 0];
cpy = cy + val[k + 1];
cx += val[k + 2];
cy += val[k + 3];
break;
case 'S':
reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
lastCmd == 'S');
path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
* cy - cpy : cy, val[k + 0], val[k + 1], val[k + 2],
val[k + 3]);
cpx = (val[k + 0]);
cpy = (val[k + 1]);
cx = val[k + 2];
cy = val[k + 3];
break;
case 'q':
path.quadTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
cy + val[k + 3]);
cpx = cx + val[k + 0];
cpy = cy + val[k + 1];
// Note that we have to update cpx first, since cx will be updated here.
cx += val[k + 2];
cy += val[k + 3];
break;
case 'Q':
path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
cx = val[k + 2];
cy = val[k + 3];
cpx = val[k + 0];
cpy = val[k + 1];
break;
case 't':
reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
lastCmd == 'T');
tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
path.quadTo(tempReflectedX, tempReflectedY, cx + val[k + 0],
cy + val[k + 1]);
cpx = tempReflectedX;
cpy = tempReflectedY;
cx += val[k + 0];
cy += val[k + 1];
break;
case 'T':
reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
lastCmd == 'T');
tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
path.quadTo(tempReflectedX, tempReflectedY, val[k + 0], val[k + 1]);
cx = val[k + 0];
cy = val[k + 1];
cpx = tempReflectedX;
cpy = tempReflectedY;
break;
case 'a':
// (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
drawArc(path, cx, cy, val[k + 5] + cx, val[k + 6] + cy,
val[k + 0], val[k + 1], val[k + 2], val[k + 3] != 0,
val[k + 4] != 0);
cx += val[k + 5];
cy += val[k + 6];
cpx = cx;
cpy = cy;
break;
case 'A':
drawArc(path, cx, cy, val[k + 5], val[k + 6], val[k + 0],
val[k + 1], val[k + 2], val[k + 3] != 0,
val[k + 4] != 0);
cx = val[k + 5];
cy = val[k + 6];
cpx = cx;
cpy = cy;
break;
}
lastCmd = cmd;
}
current[0] = cx;
current[1] = cy;
current[2] = cpx;
current[3] = cpy;
current[4] = loopX;
current[5] = loopY;
}
private static void drawArc(@NonNull Path2D p, float x0, float y0, float x1,
float y1, float a, float b, float theta, boolean isMoreThanHalf,
boolean isPositiveArc) {
LOGGER.log(Level.FINE, "(" + x0 + "," + y0 + ")-(" + x1 + "," + y1
+ ") {" + a + " " + b + "}");
/* Convert rotation angle from degrees to radians */
double thetaD = theta * Math.PI / 180.0f;
/* Pre-compute rotation matrix entries */
double cosTheta = Math.cos(thetaD);
double sinTheta = Math.sin(thetaD);
/* Transform (x0, y0) and (x1, y1) into unit space */
/* using (inverse) rotation, followed by (inverse) scale */
double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
LOGGER.log(Level.FINE, "unit space (" + x0p + "," + y0p + ")-(" + x1p
+ "," + y1p + ")");
/* Compute differences and averages */
double dx = x0p - x1p;
double dy = y0p - y1p;
double xm = (x0p + x1p) / 2;
double ym = (y0p + y1p) / 2;
/* Solve for intersecting unit circles */
double dsq = dx * dx + dy * dy;
if (dsq == 0.0) {
LOGGER.log(Level.FINE, " Points are coincident");
return; /* Points are coincident */
}
double disc = 1.0 / dsq - 1.0 / 4.0;
if (disc < 0.0) {
LOGGER.log(Level.FINE, "Points are too far apart " + dsq);
float adjust = (float) (Math.sqrt(dsq) / 1.99999);
drawArc(p, x0, y0, x1, y1, a * adjust, b * adjust, theta,
isMoreThanHalf, isPositiveArc);
return; /* Points are too far apart */
}
double s = Math.sqrt(disc);
double sdx = s * dx;
double sdy = s * dy;
double cx;
double cy;
if (isMoreThanHalf == isPositiveArc) {
cx = xm - sdy;
cy = ym + sdx;
} else {
cx = xm + sdy;
cy = ym - sdx;
}
double eta0 = Math.atan2((y0p - cy), (x0p - cx));
LOGGER.log(Level.FINE, "eta0 = Math.atan2( " + (y0p - cy) + " , "
+ (x0p - cx) + ") = " + Math.toDegrees(eta0));
double eta1 = Math.atan2((y1p - cy), (x1p - cx));
LOGGER.log(Level.FINE, "eta1 = Math.atan2( " + (y1p - cy) + " , "
+ (x1p - cx) + ") = " + Math.toDegrees(eta1));
double sweep = (eta1 - eta0);
if (isPositiveArc != (sweep >= 0)) {
if (sweep > 0) {
sweep -= 2 * Math.PI;
} else {
sweep += 2 * Math.PI;
}
}
cx *= a;
cy *= b;
double tcx = cx;
cx = cx * cosTheta - cy * sinTheta;
cy = tcx * sinTheta + cy * cosTheta;
LOGGER.log(
Level.FINE,
"cx, cy, a, b, x0, y0, thetaD, eta0, sweep = " + cx + " , "
+ cy + " , " + a + " , " + b + " , " + x0 + " , " + y0
+ " , " + Math.toDegrees(thetaD) + " , "
+ Math.toDegrees(eta0) + " , " + Math.toDegrees(sweep));
arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
}
/**
* Converts an arc to cubic Bezier segments and records them in p.
*
* @param p The target for the cubic Bezier segments
* @param cx The x coordinate center of the ellipse
* @param cy The y coordinate center of the ellipse
* @param a The radius of the ellipse in the horizontal direction
* @param b The radius of the ellipse in the vertical direction
* @param e1x E(eta1) x coordinate of the starting point of the arc
* @param e1y E(eta2) y coordinate of the starting point of the arc
* @param theta The angle that the ellipse bounding rectangle makes with the horizontal
* plane
* @param start The start angle of the arc on the ellipse
* @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
*/
private static void arcToBezier(@NonNull Path2D p, double cx, double cy, double a,
double b, double e1x, double e1y, double theta, double start,
double sweep) {
// Taken from equations at:
// http://spaceroots.org/documents/ellipse/node8.html
// and http://www.spaceroots.org/documents/ellipse/node22.html
// Maximum of 45 degrees per cubic Bezier segment
int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI));
double eta1 = start;
double cosTheta = Math.cos(theta);
double sinTheta = Math.sin(theta);
double cosEta1 = Math.cos(eta1);
double sinEta1 = Math.sin(eta1);
double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
double anglePerSegment = sweep / numSegments;
for (int i = 0; i < numSegments; i++) {
double eta2 = eta1 + anglePerSegment;
double sinEta2 = Math.sin(eta2);
double cosEta2 = Math.cos(eta2);
double e2x = cx + (a * cosTheta * cosEta2)
- (b * sinTheta * sinEta2);
double e2y = cy + (a * sinTheta * cosEta2)
+ (b * cosTheta * sinEta2);
double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
double tanDiff2 = Math.tan((eta2 - eta1) / 2);
double alpha = Math.sin(eta2 - eta1)
* (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
double q1x = e1x + alpha * ep1x;
double q1y = e1y + alpha * ep1y;
double q2x = e2x - alpha * ep2x;
double q2y = e2y - alpha * ep2y;
p.curveTo((float) q1x, (float) q1y, (float) q2x, (float) q2y,
(float) e2x, (float) e2y);
eta1 = eta2;
e1x = e2x;
e1y = e2y;
ep1x = ep2x;
ep1y = ep2y;
}
}
}
}

View File

@ -1,44 +0,0 @@
/*
* Copyright (C) 2014 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 com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.view.KeyEvent;
/**
* Delegate used to provide new implementation of few methods in {@link TimePickerClockDelegate}.
*/
public class TimePickerClockDelegate_Delegate {
// Copied from TimePickerClockDelegate.
private static final int AM = 0;
private static final int PM = 1;
@LayoutlibDelegate
static int getAmOrPmKeyCode(TimePickerClockDelegate tpcd, int amOrPm) {
// We don't care about locales here.
if (amOrPm == AM) {
return KeyEvent.KEYCODE_A;
} else if (amOrPm == PM) {
return KeyEvent.KEYCODE_P;
} else {
assert false : "amOrPm value in TimePickerSpinnerDelegate can only be 0 or 1";
return -1;
}
}
}

View File

@ -36,9 +36,9 @@ import android.widget.TextView;
/**
* A Helper class to do fake data binding in {@link AdapterView} objects.
*/
@SuppressWarnings("deprecation")
public class AdapterHelper {
@SuppressWarnings("deprecation")
static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
LayoutlibCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
// we don't care about recycling here because we never scroll.

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2016 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 libcore.util;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
/**
* Delegate implementing the native methods of {@link NativeAllocationRegistry}
*
* Through the layoutlib_create tool, the original native methods of NativeAllocationRegistry have
* been replaced by calls to methods of the same name in this delegate class.
*
* This class behaves like the original native implementation, but in Java, keeping previously
* native data into its own objects and mapping them to int that are sent back and forth between
* it and the original NativeAllocationRegistry class.
*
* @see DelegateManager
*/
public class NativeAllocationRegistry_Delegate {
// ---- delegate manager ----
private static final DelegateManager<NativeAllocationRegistry_Delegate> sManager =
new DelegateManager<>(NativeAllocationRegistry_Delegate.class);
private final FreeFunction mFinalizer;
private NativeAllocationRegistry_Delegate(FreeFunction finalizer) {
mFinalizer = finalizer;
}
/**
* The result of this method should be cached by the class and reused.
*/
public static long createFinalizer(FreeFunction finalizer) {
return sManager.addNewDelegate(new NativeAllocationRegistry_Delegate(finalizer));
}
@LayoutlibDelegate
/*package*/ static void applyFreeFunction(long freeFunction, long nativePtr) {
NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction);
if (delegate != null) {
delegate.mFinalizer.free(nativePtr);
}
}
public interface FreeFunction {
void free(long nativePtr);
}
}

View File

@ -19,7 +19,6 @@ include $(CLEAR_VARS)
# Only compile source java files in this lib.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_RESOURCE_DIRS := res
LOCAL_JAVACFLAGS := -source 6 -target 6
LOCAL_MODULE := layoutlib-tests
LOCAL_MODULE_TAGS := optional

View File

@ -75,8 +75,12 @@ public class ImageUtils {
}
}
else {
BufferedImage goldenImage = ImageIO.read(is);
assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE);
try {
BufferedImage goldenImage = ImageIO.read(is);
assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE);
} finally {
is.close();
}
}
}

View File

@ -176,17 +176,6 @@ public abstract class AbstractClassAdapter extends ClassVisitor {
}
}
/* Java 7 verifies the StackMapTable of a class if its version number is greater than 50.0.
* However, the check is disabled if the class version number is 50.0 or less. Generation
* of the StackMapTable requires a rewrite using the tree API of ASM. As a workaround,
* we rewrite the version number of the class to be 50.0
*
* http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6693236
*/
if (version > 50) {
version = 50;
}
super.visit(version, access, name, signature, superName, interfaces);
}

View File

@ -144,11 +144,8 @@ public final class CreateInfo implements ICreateInfo {
InjectMethodRunnable.class,
InjectMethodRunnables.class,
/* Java package classes */
AutoCloseable.class,
Objects.class,
IntegralToString.class,
UnsafeByteSequence.class,
Charsets.class,
System_Delegate.class,
LinkedHashMap_Delegate.class,
};
@ -169,6 +166,7 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.BitmapFactory#setDensityFromOptions",
"android.graphics.drawable.GradientDrawable#buildRing",
"android.graphics.Typeface#getSystemFontConfigLocation",
"android.graphics.Typeface#makeFamilyFromParsed",
"android.os.Handler#sendMessageAtTime",
"android.os.HandlerThread#run",
"android.preference.Preference#getView",
@ -188,6 +186,7 @@ public final class CreateInfo implements ICreateInfo {
"android.view.WindowManagerGlobal#getWindowManagerService",
"android.view.inputmethod.InputMethodManager#getInstance",
"android.view.MenuInflater#registerMenu",
"android.view.RenderNode#getMatrix",
"android.view.RenderNode#nCreate",
"android.view.RenderNode#nDestroyRenderNode",
"android.view.RenderNode#nSetElevation",
@ -200,7 +199,6 @@ public final class CreateInfo implements ICreateInfo {
"android.view.RenderNode#nGetTranslationZ",
"android.view.RenderNode#nSetRotation",
"android.view.RenderNode#nGetRotation",
"android.view.RenderNode#getMatrix",
"android.view.RenderNode#nSetLeft",
"android.view.RenderNode#nSetTop",
"android.view.RenderNode#nSetRight",
@ -216,7 +214,6 @@ public final class CreateInfo implements ICreateInfo {
"android.view.RenderNode#nGetScaleY",
"android.view.RenderNode#nIsPivotExplicitlySet",
"android.view.ViewGroup#drawChild",
"android.widget.TimePickerClockDelegate#getAmOrPmKeyCode",
"com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
"com.android.internal.util.XmlUtils#convertValueToInt",
"com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
@ -224,6 +221,7 @@ public final class CreateInfo implements ICreateInfo {
"libcore.io.MemoryMappedFile#mmapRO",
"libcore.io.MemoryMappedFile#close",
"libcore.io.MemoryMappedFile#bigEndianIterator",
"libcore.util.NativeAllocationRegistry#applyFreeFunction",
};
/**
@ -274,6 +272,7 @@ public final class CreateInfo implements ICreateInfo {
"android.os.SystemProperties",
"android.text.AndroidBidi",
"android.text.StaticLayout",
"android.util.PathParser",
"android.view.Display",
"libcore.icu.ICU",
};
@ -306,12 +305,9 @@ public final class CreateInfo implements ICreateInfo {
*/
private final static String[] JAVA_PKG_CLASSES =
new String[] {
"java.lang.AutoCloseable", "com.android.tools.layoutlib.java.AutoCloseable",
"java.util.Objects", "com.android.tools.layoutlib.java.Objects",
"java.nio.charset.Charsets", "com.android.tools.layoutlib.java.Charsets",
"java.nio.charset.Charsets", "java.nio.charset.StandardCharsets",
"java.lang.IntegralToString", "com.android.tools.layoutlib.java.IntegralToString",
"java.lang.UnsafeByteSequence", "com.android.tools.layoutlib.java.UnsafeByteSequence",
"java.nio.charset.StandardCharsets", "com.android.tools.layoutlib.java.Charsets",
};
private final static String[] EXCLUDED_CLASSES =

View File

@ -103,6 +103,7 @@ class StubMethodAdapter extends MethodVisitor {
mParentVisitor.visitInsn(Opcodes.ICONST_1);
mParentVisitor.visitInsn(Opcodes.IRETURN);
mParentVisitor.visitLabel(l1);
mParentVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mParentVisitor.visitInsn(Opcodes.ICONST_0);
break;
case Type.CHAR: