Skip to content

Commit 2625e2f

Browse files
committed
[Samples] Updating to iink 2.3
1 parent 41417f3 commit 2625e2f

File tree

8 files changed

+430
-107
lines changed

8 files changed

+430
-107
lines changed

samples/UIReferenceImplementation/src/main/java/com/myscript/iink/uireferenceimplementation/Canvas.java

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,16 @@
3232

3333
import java.util.HashSet;
3434
import java.util.Map;
35+
import java.util.Objects;
3536
import java.util.Set;
3637

3738
public class Canvas implements ICanvas
3839
{
3940

4041
private static final Style DEFAULT_SVG_STYLE = new Style();
4142

42-
@NonNull
43-
private final android.graphics.Canvas canvas;
43+
@Nullable
44+
private android.graphics.Canvas canvas;
4445

4546
@NonNull
4647
private final Paint strokePaint;
@@ -77,6 +78,8 @@ public class Canvas implements ICanvas
7778
private final ImageLoader imageLoader;
7879
private final OfflineSurfaceManager offlineSurfaceManager;
7980

81+
private boolean clearOnStartDraw = true;
82+
8083
private final Set<String> clips;
8184

8285
private final Map<String, Typeface> typefaceMap;
@@ -92,7 +95,7 @@ public class Canvas implements ICanvas
9295
@NonNull
9396
private final Matrix pointScaleMatrix;
9497

95-
public Canvas(@NonNull android.graphics.Canvas canvas, Map<String, Typeface> typefaceMap, ImageLoader imageLoader, @Nullable OfflineSurfaceManager offlineSurfaceManager, float xdpi, float ydpi)
98+
public Canvas(@Nullable android.graphics.Canvas canvas, Map<String, Typeface> typefaceMap, ImageLoader imageLoader, @Nullable OfflineSurfaceManager offlineSurfaceManager, float xdpi, float ydpi)
9699
{
97100
this.canvas = canvas;
98101
this.typefaceMap = typefaceMap;
@@ -135,11 +138,21 @@ public Canvas(@NonNull android.graphics.Canvas canvas, Map<String, Typeface> typ
135138
applyStyle(DEFAULT_SVG_STYLE);
136139
}
137140

138-
public Canvas(@NonNull android.graphics.Canvas canvas, Map<String, Typeface> typefaceMap, ImageLoader imageLoader, float xdpi, float ydpi)
141+
public Canvas(@Nullable android.graphics.Canvas canvas, Map<String, Typeface> typefaceMap, ImageLoader imageLoader, float xdpi, float ydpi)
139142
{
140143
this(canvas, typefaceMap, imageLoader, null, xdpi, ydpi);
141144
}
142145

146+
public void setCanvas(@NonNull android.graphics.Canvas canvas)
147+
{
148+
this.canvas = canvas;
149+
}
150+
151+
public void setClearOnStartDraw(boolean clearOnStartDraw)
152+
{
153+
this.clearOnStartDraw = clearOnStartDraw;
154+
}
155+
143156
private void applyStyle(@NonNull Style style)
144157
{
145158
setStrokeColor(style.getStrokeColor());
@@ -174,6 +187,7 @@ public void setTransform(@NonNull Transform transform)
174187
transformValues[Matrix.MSCALE_Y] = (float) transform.yy;
175188
transformValues[Matrix.MTRANS_Y] = (float) transform.ty;
176189

190+
Objects.requireNonNull(canvas);
177191
transformMatrix.setValues(transformValues);
178192
canvas.setMatrix(transformMatrix);
179193

@@ -313,6 +327,7 @@ public final void setFontProperties(@NonNull String fontFamily, float fontLineHe
313327
@Override
314328
public void startDraw(int x, int y, int width, int height)
315329
{
330+
Objects.requireNonNull(canvas);
316331
canvas.save();
317332

318333
pointsCache[0] = x;
@@ -322,7 +337,7 @@ public void startDraw(int x, int y, int width, int height)
322337

323338
// When offscreen rendering is supported, clear the destination
324339
// Otherwise, do not clear the destination (e.g. when exporting image, we want a white background)
325-
if (offlineSurfaceManager != null)
340+
if (offlineSurfaceManager != null && clearOnStartDraw)
326341
canvas.drawRect(pointsCache[0], pointsCache[1], pointsCache[2], pointsCache[3], clearPaint);
327342

328343
// Hardware canvas does not support PorterDuffXfermode
@@ -332,6 +347,7 @@ public void startDraw(int x, int y, int width, int height)
332347
@Override
333348
public void endDraw()
334349
{
350+
Objects.requireNonNull(canvas);
335351
canvas.restore();
336352
}
337353

@@ -340,6 +356,7 @@ public void startGroup(@NonNull String id, float x, float y, float width, float
340356
{
341357
if (clipContent)
342358
{
359+
Objects.requireNonNull(canvas);
343360
clips.add(id);
344361
canvas.save();
345362

@@ -352,6 +369,7 @@ public void endGroup(@NonNull String id)
352369
{
353370
if (clips.remove(id))
354371
{
372+
Objects.requireNonNull(canvas);
355373
canvas.restore();
356374
}
357375
}
@@ -378,6 +396,7 @@ public final IPath createPath()
378396
@Override
379397
public void drawPath(@NonNull IPath ipath)
380398
{
399+
Objects.requireNonNull(canvas);
381400
Path path = (Path) ipath;
382401

383402
if (android.graphics.Color.alpha(fillPaint.getColor()) != 0)
@@ -394,6 +413,7 @@ public void drawPath(@NonNull IPath ipath)
394413
@Override
395414
public void drawRectangle(float x, float y, float width, float height)
396415
{
416+
Objects.requireNonNull(canvas);
397417
if (android.graphics.Color.alpha(fillPaint.getColor()) != 0)
398418
{
399419
canvas.drawRect(x, y, x + width, y + height, fillPaint);
@@ -407,6 +427,7 @@ public void drawRectangle(float x, float y, float width, float height)
407427
@Override
408428
public void drawLine(float x1, float y1, float x2, float y2)
409429
{
430+
Objects.requireNonNull(canvas);
410431
canvas.drawLine(x1, y1, x2, y2, strokePaint);
411432
}
412433

@@ -416,16 +437,16 @@ public void drawObject(@NonNull String url, @NonNull String mimeType, float x, f
416437
if (imageLoader == null)
417438
return;
418439

419-
Point screenMin = new Point(x, y);
420-
transform.apply(screenMin);
421-
Point screenMax = new Point(x + width, y + height);
422-
transform.apply(screenMax);
440+
Objects.requireNonNull(canvas);
441+
442+
RectF pixelSize = new RectF(x,y,x + width, y + height);
443+
transformMatrix.mapRect(pixelSize);
423444

424445
final Rect targetRect = new Rect(
425-
(int) Math.floor(screenMin.x),
426-
(int) Math.floor(screenMin.y),
427-
(int) (Math.ceil(screenMax.x) - x),
428-
(int) (Math.ceil(screenMax.y) - y));
446+
(int) Math.floor(pixelSize.left),
447+
(int) Math.floor(pixelSize.top),
448+
(int) (Math.ceil(pixelSize.right)),
449+
(int) (Math.ceil(pixelSize.bottom)));
429450

430451
synchronized (imageLoader)
431452
{
@@ -441,22 +462,6 @@ public void drawObject(@NonNull String url, @NonNull String mimeType, float x, f
441462
}
442463
else
443464
{
444-
// adjust rectangle so that the image gets fit into original rectangle
445-
float fx = width / image.getWidth();
446-
float fy = height / image.getHeight();
447-
if (fx > fy)
448-
{
449-
float w = image.getWidth() * fy;
450-
x += (width - w) / 2;
451-
width = w;
452-
}
453-
else
454-
{
455-
float h = image.getHeight() * fx;
456-
y += (height - h) / 2;
457-
height = h;
458-
}
459-
460465
// draw the image
461466
Rect srcRect = new Rect(0, 0, image.getWidth(), image.getHeight());
462467
RectF dstRect = new RectF(x, y, x + width, y + height);
@@ -471,6 +476,7 @@ public void drawObject(@NonNull String url, @NonNull String mimeType, float x, f
471476
@Override
472477
public void drawText(@NonNull String label, float x, float y, float xmin, float ymin, float xmax, float ymax)
473478
{
479+
Objects.requireNonNull(canvas);
474480
// transform the insertion point so that it is not impacted by text scale
475481
pointsCache[0] = x;
476482
pointsCache[1] = y;
@@ -496,6 +502,7 @@ public void blendOffscreen(int id, float srcX, float srcY, float srcWidth, float
496502

497503
if (bitmap != null)
498504
{
505+
Objects.requireNonNull(canvas);
499506
floatRectCache.set(destX, destY, destX + destWidth, destY + destHeight);
500507
simpleRectCache.set(Math.round(srcX), Math.round(srcY),
501508
Math.round(srcX + srcWidth), Math.round(srcY + srcHeight));
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright 2023 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
// Adapted from:
18+
// https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:input/input-motionprediction/
19+
20+
package com.myscript.iink.uireferenceimplementation;
21+
22+
import android.content.Context;
23+
import android.os.Build;
24+
import android.view.Display;
25+
import android.view.WindowManager;
26+
27+
import androidx.annotation.DoNotInline;
28+
import androidx.annotation.NonNull;
29+
import androidx.annotation.RequiresApi;
30+
31+
/**
32+
* Get screen fastest refresh rate (in ms)
33+
*/
34+
@SuppressWarnings("deprecation")
35+
public class FrameTimeEstimator {
36+
private static final float LEGACY_FRAME_TIME_MS = 16f;
37+
private static final float MS_IN_A_SECOND = 1000f;
38+
39+
static public float getFrameTime(@NonNull Context context)
40+
{
41+
return getFastestFrameTimeMs(context);
42+
}
43+
44+
private static Display getDisplayForContext(Context context)
45+
{
46+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
47+
{
48+
return Api30Impl.getDisplayForContext(context);
49+
}
50+
return ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
51+
}
52+
53+
private static float getFastestFrameTimeMs(Context context)
54+
{
55+
Display defaultDisplay = getDisplayForContext(context);
56+
57+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
58+
{
59+
return Api23Impl.getFastestFrameTimeMs(defaultDisplay);
60+
}
61+
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
62+
{
63+
return Api21Impl.getFastestFrameTimeMs(defaultDisplay);
64+
}
65+
else
66+
{
67+
return LEGACY_FRAME_TIME_MS;
68+
}
69+
}
70+
71+
@SuppressWarnings("deprecation")
72+
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
73+
static class Api21Impl
74+
{
75+
private Api21Impl()
76+
{
77+
// Not instantiable
78+
}
79+
80+
@DoNotInline
81+
static float getFastestFrameTimeMs(Display display)
82+
{
83+
float[] refreshRates = display.getSupportedRefreshRates();
84+
float largestRefreshRate = refreshRates[0];
85+
86+
for (int c = 1; c < refreshRates.length; c++)
87+
{
88+
if (refreshRates[c] > largestRefreshRate)
89+
largestRefreshRate = refreshRates[c];
90+
}
91+
92+
return MS_IN_A_SECOND / largestRefreshRate;
93+
}
94+
}
95+
96+
@RequiresApi(Build.VERSION_CODES.M)
97+
static class Api23Impl
98+
{
99+
private Api23Impl()
100+
{
101+
// Not instantiable
102+
}
103+
104+
@DoNotInline
105+
static float getFastestFrameTimeMs(Display display)
106+
{
107+
Display.Mode[] displayModes = display.getSupportedModes();
108+
float largestRefreshRate = displayModes[0].getRefreshRate();
109+
110+
for (int c = 1; c < displayModes.length; c++)
111+
{
112+
float currentRefreshRate = displayModes[c].getRefreshRate();
113+
if (currentRefreshRate > largestRefreshRate)
114+
largestRefreshRate = currentRefreshRate;
115+
}
116+
117+
return MS_IN_A_SECOND / largestRefreshRate;
118+
}
119+
}
120+
121+
@RequiresApi(Build.VERSION_CODES.R)
122+
static class Api30Impl
123+
{
124+
private Api30Impl()
125+
{
126+
// Not instantiable
127+
}
128+
129+
@DoNotInline
130+
static Display getDisplayForContext(Context context)
131+
{
132+
return context.getDisplay();
133+
}
134+
}
135+
}

0 commit comments

Comments
 (0)