summaryrefslogtreecommitdiff
path: root/graphics/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/java/android')
-rw-r--r--graphics/java/android/graphics/SurfaceTexture.java12
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java49
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java5
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java10
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java60
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java22
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java40
-rw-r--r--graphics/java/android/graphics/pdf/PdfEditor.java65
-rw-r--r--graphics/java/android/graphics/pdf/PdfRenderer.java37
9 files changed, 243 insertions, 57 deletions
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 5c54324d8107..c3861083e2fd 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -77,6 +77,8 @@ public class SurfaceTexture {
private long mProducer;
private long mFrameAvailableListener;
+ private boolean mIsSingleBuffered;
+
/**
* Callback interface for being notified that a new stream frame is available.
*/
@@ -130,6 +132,7 @@ public class SurfaceTexture {
*/
public SurfaceTexture(int texName, boolean singleBufferMode) {
mCreatorLooper = Looper.myLooper();
+ mIsSingleBuffered = singleBufferMode;
nativeInit(false, texName, singleBufferMode, new WeakReference<SurfaceTexture>(this));
}
@@ -157,6 +160,7 @@ public class SurfaceTexture {
*/
public SurfaceTexture(boolean singleBufferMode) {
mCreatorLooper = Looper.myLooper();
+ mIsSingleBuffered = singleBufferMode;
nativeInit(true, 0, singleBufferMode, new WeakReference<SurfaceTexture>(this));
}
@@ -378,6 +382,14 @@ public class SurfaceTexture {
}
}
+ /**
+ * Returns true if the SurfaceTexture is single-buffered
+ * @hide
+ */
+ public boolean isSingleBuffered() {
+ return mIsSingleBuffered;
+ }
+
private native void nativeInit(boolean isDetached, int texName,
boolean singleBufferMode, WeakReference<SurfaceTexture> weakSelf)
throws Surface.OutOfResourcesException;
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index c836204486b0..0f305f3cff3d 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -144,6 +144,55 @@ import java.util.ArrayList;
* android:valueType=&quot;pathType&quot;/&gt;
* &lt;/set&gt;
* </pre></li>
+ * <p>
+ * Since AAPT tool is now supporting a new format which can bundle several related XML files into
+ * one, we can merge the previous example into one XML file, like this:
+ * </p>
+ * <pre>
+ * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; &gt;
+ * &lt;aapt:attr name="android:drawable"&gt;
+ * &lt;vector
+ * android:height=&quot;64dp&quot;
+ * android:width=&quot;64dp&quot;
+ * android:viewportHeight=&quot;600&quot;
+ * android:viewportWidth=&quot;600&quot; &gt;
+ * &lt;group
+ * android:name=&quot;rotationGroup&quot;
+ * android:pivotX=&quot;300.0&quot;
+ * android:pivotY=&quot;300.0&quot;
+ * android:rotation=&quot;45.0&quot; &gt;
+ * &lt;path
+ * android:name=&quot;v&quot;
+ * android:fillColor=&quot;#000000&quot;
+ * android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
+ * &lt;/group&gt;
+ * &lt;/vector&gt;
+ * &lt;/aapt:attr&gt;
+ *
+ * &lt;target android:name=&quot;rotationGroup&quot;&gt; *
+ * &lt;aapt:attr name="android:animation"&gt;
+ * &lt;objectAnimator
+ * android:duration=&quot;6000&quot;
+ * android:propertyName=&quot;rotation&quot;
+ * android:valueFrom=&quot;0&quot;
+ * android:valueTo=&quot;360&quot; /&gt;
+ * &lt;/aapt:attr&gt;
+ * &lt;/target&gt;
+ *
+ * &lt;target android:name=&quot;v&quot; &gt;
+ * &lt;aapt:attr name="android:animation"&gt;
+ * &lt;set&gt;
+ * &lt;objectAnimator
+ * android:duration=&quot;3000&quot;
+ * android:propertyName=&quot;pathData&quot;
+ * android:valueFrom=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot;
+ * android:valueTo=&quot;M300,70 l 0,-70 70,0 0,140 -70,0 z&quot;
+ * android:valueType=&quot;pathType&quot;/&gt;
+ * &lt;/set&gt;
+ * &lt;/aapt:attr&gt;
+ * &lt;/target&gt;
+ * &lt;/animated-vector&gt;
+ * </pre>
*
* @attr ref android.R.styleable#AnimatedVectorDrawable_drawable
* @attr ref android.R.styleable#AnimatedVectorDrawableTarget_name
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 7f3a4373639b..3aca867c0347 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1422,9 +1422,10 @@ public abstract class Drawable {
/**
* Obtains styled attributes from the theme, if available, or unstyled
* resources if the theme is null.
+ * @hide
*/
- static @NonNull TypedArray obtainAttributes(@NonNull Resources res, @Nullable Theme theme,
- @NonNull AttributeSet set, @NonNull int[] attrs) {
+ protected static @NonNull TypedArray obtainAttributes(@NonNull Resources res,
+ @Nullable Theme theme, @NonNull AttributeSet set, @NonNull int[] attrs) {
if (theme == null) {
return res.obtainAttributes(set, attrs);
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index cc7f5c7cf753..c7a3c75f3545 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -27,8 +27,8 @@ import android.graphics.ColorFilter;
import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.LayoutDirection;
@@ -601,8 +601,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
* during inflation.
*
* @param res the resources used to inflate density-dependent values
+ * @hide
*/
- final void updateDensity(Resources res) {
+ protected final void updateDensity(Resources res) {
mDrawableContainerState.updateDensity(res);
}
@@ -711,7 +712,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
boolean mHasTintList;
boolean mHasTintMode;
- DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
+ /**
+ * @hide
+ */
+ protected DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
Resources res) {
mOwner = owner;
mSourceRes = res != null ? res : (orig != null ? orig.mSourceRes : null);
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 3dbd2a96b00a..8c633b0da93a 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -475,16 +475,17 @@ public class GradientDrawable extends Drawable {
}
/**
- * Sets the center location in pixels of the gradient. The radius is
- * honored only when the gradient type is set to {@link #RADIAL_GRADIENT}
- * or {@link #SWEEP_GRADIENT}.
+ * Sets the position of the center of the gradient as a fraction of the
+ * width and height.
+ * <p>
+ * The default value is (0.5, 0.5).
* <p>
* <strong>Note</strong>: changing this property will affect all instances
* of a drawable loaded from a resource. It is recommended to invoke
* {@link #mutate()} before changing this property.
*
- * @param x the x coordinate of the gradient's center in pixels
- * @param y the y coordinate of the gradient's center in pixels
+ * @param x the X-position of the center of the gradient
+ * @param y the Y-position of the center of the gradient
*
* @see #mutate()
* @see #setGradientType(int)
@@ -498,9 +499,10 @@ public class GradientDrawable extends Drawable {
}
/**
- * Returns the center X location of this gradient in pixels.
+ * Returns the X-position of the center of the gradient as a fraction of
+ * the width.
*
- * @return the center X location of this gradient in pixels
+ * @return the X-position of the center of the gradient
* @see #setGradientCenter(float, float)
*/
public float getGradientCenterX() {
@@ -508,9 +510,10 @@ public class GradientDrawable extends Drawable {
}
/**
- * Returns the center Y location of this gradient in pixels.
+ * Returns the Y-position of the center of this gradient as a fraction of
+ * the height.
*
- * @return the center Y location of this gradient in pixels
+ * @return the Y-position of the center of the gradient
* @see #setGradientCenter(float, float)
*/
public float getGradientCenterY() {
@@ -554,19 +557,43 @@ public class GradientDrawable extends Drawable {
}
/**
- * Sets whether or not this drawable will honor its {@code level} property.
+ * Sets whether this drawable's {@code level} property will be used to
+ * scale the gradient. If a gradient is not used, this property has no
+ * effect.
* <p>
- * <strong>Note</strong>: changing this property will affect all instances
+ * Scaling behavior varies based on gradient type:
+ * <ul>
+ * <li>{@link #LINEAR_GRADIENT} adjusts the ending position along the
+ * gradient's axis of orientation (see {@link #getOrientation()})
+ * <li>{@link #RADIAL_GRADIENT} adjusts the outer radius
+ * <li>{@link #SWEEP_GRADIENT} adjusts the ending angle
+ * <ul>
+ * <p>
+ * The default value for this property is {@code false}.
+ * <p>
+ * <strong>Note</strong>: This property corresponds to the
+ * {@code android:useLevel} attribute on the inner {@code &lt;gradient&gt;}
+ * tag, NOT the {@code android:useLevel} attribute on the outer
+ * {@code &lt;shape&gt;} tag. For example,
+ * <pre>{@code
+ * <shape ...>
+ * <gradient
+ * ...
+ * android:useLevel="true" />
+ * </shape>
+ * }</pre><p>
+ * <strong>Note</strong>: Changing this property will affect all instances
* of a drawable loaded from a resource. It is recommended to invoke
* {@link #mutate()} before changing this property.
*
- * @param useLevel {@code true} if this drawable should honor its level,
- * {@code false} otherwise
+ * @param useLevel {@code true} if the gradient should be scaled based on
+ * level, {@code false} otherwise
*
* @see #mutate()
* @see #setLevel(int)
* @see #getLevel()
* @see #getUseLevel()
+ * @attr ref android.R.styleable#GradientDrawableGradient_useLevel
*/
public void setUseLevel(boolean useLevel) {
mGradientState.mUseLevel = useLevel;
@@ -575,12 +602,13 @@ public class GradientDrawable extends Drawable {
}
/**
- * Returns whether or not this drawable will honor its {@code level}
- * property.
+ * Returns whether this drawable's {@code level} property will be used to
+ * scale the gradient.
*
- * @return {@code true} if this drawable should honor its level,
+ * @return {@code true} if the gradient should be scaled based on level,
* {@code false} otherwise
* @see #setUseLevel(boolean)
+ * @attr ref android.R.styleable#GradientDrawableGradient_useLevel
*/
public boolean getUseLevel() {
return mGradientState.mUseLevel;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 1864206118b2..c30c4c2f02d6 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -269,7 +269,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
// If the layer doesn't have a drawable or unresolved theme
// attribute for a drawable, attempt to parse one from the child
- // element.
+ // element. If multiple child elements exist, we'll only use the
+ // first one.
if (layer.mDrawable == null && (layer.mThemeAttrs == null ||
layer.mThemeAttrs[R.styleable.LayerDrawableItem_drawable] == 0)) {
while ((type = parser.next()) == XmlPullParser.TEXT) {
@@ -279,13 +280,12 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
+ ": <item> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
- layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme);
- }
- if (layer.mDrawable != null) {
+ // We found a child drawable. Take ownership.
+ layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme);
+ layer.mDrawable.setCallback(this);
state.mChildrenChangingConfigurations |=
layer.mDrawable.getChangingConfigurations();
- layer.mDrawable.setCallback(this);
}
addLayer(layer);
@@ -387,7 +387,19 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
final Drawable dr = a.getDrawable(R.styleable.LayerDrawableItem_drawable);
if (dr != null) {
+ if (layer.mDrawable != null) {
+ // It's possible that a drawable was already set, in which case
+ // we should clear the callback. We may have also integrated the
+ // drawable's changing configurations, but we don't have enough
+ // information to revert that change.
+ layer.mDrawable.setCallback(null);
+ }
+
+ // Take ownership of the new drawable.
layer.mDrawable = dr;
+ layer.mDrawable.setCallback(this);
+ state.mChildrenChangingConfigurations |=
+ layer.mDrawable.getChangingConfigurations();
}
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index dc1d18f3b2bd..9ff69650294d 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -27,9 +27,9 @@ import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Insets;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
-import android.graphics.PorterDuff.Mode;
import android.graphics.Shader;
import android.util.ArrayMap;
import android.util.AttributeSet;
@@ -140,12 +140,16 @@ import dalvik.system.VMRuntime;
* in the SVG's path data. This is defined in the viewport space.</dd>
* <dt><code>android:fillColor</code></dt>
* <dd>Specifies the color used to fill the path. May be a color or, for SDK 24+, a color state list
- * or a gradient color. If this property is animated, any value set by the animation will
- * override the original value. No path fill is drawn if this property is not specified.</dd>
+ * or a gradient color (See {@link android.R.styleable#GradientColor}
+ * and {@link android.R.styleable#GradientColorItem}).
+ * If this property is animated, any value set by the animation will override the original value.
+ * No path fill is drawn if this property is not specified.</dd>
* <dt><code>android:strokeColor</code></dt>
* <dd>Specifies the color used to draw the path outline. May be a color or, for SDK 24+, a color
- * state list or a gradient color. If this property is animated, any value set by the animation will
- * override the original value. No path outline is drawn if this property is not specified.</dd>
+ * state list or a gradient color (See {@link android.R.styleable#GradientColor}
+ * and {@link android.R.styleable#GradientColorItem}).
+ * If this property is animated, any value set by the animation will override the original value.
+ * No path outline is drawn if this property is not specified.</dd>
* <dt><code>android:strokeWidth</code></dt>
* <dd>The width a path stroke.</dd>
* <dt><code>android:strokeAlpha</code></dt>
@@ -166,8 +170,9 @@ import dalvik.system.VMRuntime;
* <dt><code>android:strokeMiterLimit</code></dt>
* <dd>Sets the Miter limit for a stroked path.</dd>
* <dt><code>android:fillType</code></dt>
- * <dd>Sets the fillType for a path. It is the same as SVG's "fill-rule" properties.
- * For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty</dd>
+ * <dd>Sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the
+ * same as SVG's "fill-rule" properties. For more details, see
+ * <a href="https://www.w3.org/TR/SVG/painting.html#FillRuleProperty">FillRuleProperty</a></dd>
* </dl></dd>
* </dl>
*
@@ -201,7 +206,26 @@ import dalvik.system.VMRuntime;
* android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
* &lt;/group&gt;
* &lt;/vector&gt;
- * </pre></li>
+ * </pre>
+ * </li>
+ * <li>And here is an example of linear gradient color, which is supported in SDK 24+.
+ * See more details in {@link android.R.styleable#GradientColor} and
+ * {@link android.R.styleable#GradientColorItem}.
+ * <pre>
+ * &lt;gradient xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:angle="90"
+ * android:startColor="?android:attr/colorPrimary"
+ * android:endColor="?android:attr/colorControlActivated"
+ * android:centerColor="#f00"
+ * android:startX="0"
+ * android:startY="0"
+ * android:endX="100"
+ * android:endY="100"
+ * android:type="linear"&gt;
+ * &lt;/gradient&gt;
+ * </pre>
+ * </li>
+ *
*/
public class VectorDrawable extends Drawable {
diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java
index 2b70b6a45f82..cd1f8de6ee0f 100644
--- a/graphics/java/android/graphics/pdf/PdfEditor.java
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -79,8 +79,12 @@ public final class PdfEditor {
}
mInput = input;
- mNativeDocument = nativeOpen(mInput.getFd(), size);
- mPageCount = nativeGetPageCount(mNativeDocument);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ mNativeDocument = nativeOpen(mInput.getFd(), size);
+ mPageCount = nativeGetPageCount(mNativeDocument);
+ }
+
mCloseGuard.open("close");
}
@@ -102,7 +106,10 @@ public final class PdfEditor {
public void removePage(int pageIndex) {
throwIfClosed();
throwIfPageNotInDocument(pageIndex);
- mPageCount = nativeRemovePage(mNativeDocument, pageIndex);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ mPageCount = nativeRemovePage(mNativeDocument, pageIndex);
+ }
}
/**
@@ -125,11 +132,16 @@ public final class PdfEditor {
if (clip == null) {
Point size = new Point();
getPageSize(pageIndex, size);
- nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
- 0, 0, size.x, size.y);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
+ 0, 0, size.x, size.y);
+ }
} else {
- nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
- clip.left, clip.top, clip.right, clip.bottom);
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
+ clip.left, clip.top, clip.right, clip.bottom);
+ }
}
}
@@ -143,7 +155,10 @@ public final class PdfEditor {
throwIfClosed();
throwIfOutSizeNull(outSize);
throwIfPageNotInDocument(pageIndex);
- nativeGetPageSize(mNativeDocument, pageIndex, outSize);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeGetPageSize(mNativeDocument, pageIndex, outSize);
+ }
}
/**
@@ -156,7 +171,10 @@ public final class PdfEditor {
throwIfClosed();
throwIfOutMediaBoxNull(outMediaBox);
throwIfPageNotInDocument(pageIndex);
- return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox);
+ }
}
/**
@@ -169,7 +187,10 @@ public final class PdfEditor {
throwIfClosed();
throwIfMediaBoxNull(mediaBox);
throwIfPageNotInDocument(pageIndex);
- nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox);
+ }
}
/**
@@ -182,7 +203,10 @@ public final class PdfEditor {
throwIfClosed();
throwIfOutCropBoxNull(outCropBox);
throwIfPageNotInDocument(pageIndex);
- return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox);
+ }
}
/**
@@ -195,7 +219,10 @@ public final class PdfEditor {
throwIfClosed();
throwIfCropBoxNull(cropBox);
throwIfPageNotInDocument(pageIndex);
- nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox);
+ }
}
/**
@@ -205,7 +232,10 @@ public final class PdfEditor {
*/
public boolean shouldScaleForPrinting() {
throwIfClosed();
- return nativeScaleForPrinting(mNativeDocument);
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ return nativeScaleForPrinting(mNativeDocument);
+ }
}
/**
@@ -219,7 +249,10 @@ public final class PdfEditor {
public void write(ParcelFileDescriptor output) throws IOException {
try {
throwIfClosed();
- nativeWrite(mNativeDocument, output.getFd());
+
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeWrite(mNativeDocument, output.getFd());
+ }
} finally {
IoUtils.closeQuietly(output);
}
@@ -247,7 +280,9 @@ public final class PdfEditor {
}
private void doClose() {
- nativeClose(mNativeDocument);
+ synchronized (PdfRenderer.sPdfiumLock) {
+ nativeClose(mNativeDocument);
+ }
IoUtils.closeQuietly(mInput);
mInput = null;
mCloseGuard.close();
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index 520ebe5f2db8..cfc130990e92 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -99,6 +99,12 @@ import java.lang.annotation.RetentionPolicy;
* @see #close()
*/
public final class PdfRenderer implements AutoCloseable {
+ /**
+ * Any call the native pdfium code has to be single threaded as the library does not support
+ * parallel use.
+ */
+ final static Object sPdfiumLock = new Object();
+
private final CloseGuard mCloseGuard = CloseGuard.get();
private final Point mTempPoint = new Point();
@@ -154,8 +160,12 @@ public final class PdfRenderer implements AutoCloseable {
}
mInput = input;
- mNativeDocument = nativeCreate(mInput.getFd(), size);
- mPageCount = nativeGetPageCount(mNativeDocument);
+
+ synchronized (sPdfiumLock) {
+ mNativeDocument = nativeCreate(mInput.getFd(), size);
+ mPageCount = nativeGetPageCount(mNativeDocument);
+ }
+
mCloseGuard.open("close");
}
@@ -189,7 +199,10 @@ public final class PdfRenderer implements AutoCloseable {
*/
public boolean shouldScaleForPrinting() {
throwIfClosed();
- return nativeScaleForPrinting(mNativeDocument);
+
+ synchronized (sPdfiumLock) {
+ return nativeScaleForPrinting(mNativeDocument);
+ }
}
/**
@@ -224,7 +237,9 @@ public final class PdfRenderer implements AutoCloseable {
if (mCurrentPage != null) {
mCurrentPage.close();
}
- nativeClose(mNativeDocument);
+ synchronized (sPdfiumLock) {
+ nativeClose(mNativeDocument);
+ }
try {
mInput.close();
} catch (IOException ioe) {
@@ -277,7 +292,9 @@ public final class PdfRenderer implements AutoCloseable {
private Page(int index) {
Point size = mTempPoint;
- mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size);
+ synchronized (sPdfiumLock) {
+ mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size);
+ }
mIndex = index;
mWidth = size.x;
mHeight = size.y;
@@ -384,8 +401,10 @@ public final class PdfRenderer implements AutoCloseable {
final long transformPtr = (transform != null) ? transform.native_instance : 0;
- nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft,
- contentTop, contentRight, contentBottom, transformPtr, renderMode);
+ synchronized (sPdfiumLock) {
+ nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft,
+ contentTop, contentRight, contentBottom, transformPtr, renderMode);
+ }
}
/**
@@ -412,7 +431,9 @@ public final class PdfRenderer implements AutoCloseable {
}
private void doClose() {
- nativeClosePage(mNativePage);
+ synchronized (sPdfiumLock) {
+ nativeClosePage(mNativePage);
+ }
mNativePage = 0;
mCloseGuard.close();
mCurrentPage = null;