LayoutLib fixes for N
Moves LayoutLib to Java 8 - YAY! Fix delegates Change-Id: I098996e43e330e995d33f12df1c16355bbc02f0f
This commit is contained in:
@ -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;
|
||||
|
||||
|
@ -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>
|
2
tools/layoutlib/.idea/misc.xml
generated
2
tools/layoutlib/.idea/misc.xml
generated
@ -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>
|
@ -26,4 +26,4 @@
|
||||
<ConfigurationWrapper RunnerId="Run" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
||||
</component>
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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 ----
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
@ -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*/);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ public final class Path_Delegate {
|
||||
return sManager.getDelegate(nPath);
|
||||
}
|
||||
|
||||
public Shape getJavaShape() {
|
||||
public Path2D getJavaShape() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
757
tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
Normal file
757
tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 =
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user