Коммит fb981781 создал по автору Красавин Никита Сергеевич's avatar Красавин Никита Сергеевич
Просмотр файлов

Merge branch 'move-to-flutter-3.24' into 'master'

[feature] Move to flutter 3.24.0

See merge request oss/flutter/flutter-community-plugins/pdfrx!2
владельцы e87898c2 3f78d8b7
# pdfrx # pdfrx
[Pdfrx](https://pub.dartlang.org/packages/pdfrx) plugin with Aurora support. [Pdfrx](https://pub.dartlang.org/packages/pdfrx) plugin with Aurora support.
The plugin supports Aurora, Android, iOS, Windows, macOS, Linux. The plugin supports Aurora, Android, iOS, Windows, macOS, Linux, Web.
Web support will be added after the release of flutter-aurora 3.24.
## Interactive Demo ## Interactive Demo
...@@ -82,9 +81,8 @@ It supports all the features of `pdfrx-1.0.82` and includes support for Aurora p ...@@ -82,9 +81,8 @@ It supports all the features of `pdfrx-1.0.82` and includes support for Aurora p
dependencies: dependencies:
pdfrx: pdfrx:
git: git:
url: https://gitlab.com/omprussia/flutter/flutter-plugins.git url: https://os-git.omprussia.ru/oss/flutter/flutter-community-plugins/pdfrx.git
ref: pdfrx-1.0.82 ref: pdfrx-1.0.82-aurora
path: packages/pdfrx_aurora
``` ```
***.spec** ***.spec**
......
// ignore_for_file: avoid_web_libraries_in_flutter
@JS()
library pdf.js;
import 'dart:js_interop';
import 'dart:js_interop_unsafe';
import 'dart:typed_data';
import 'package:synchronized/extension.dart';
import 'package:web/web.dart' as web;
import '../../pdfrx.dart';
/// Default pdf.js version
const _pdfjsVersion = '4.4.168';
/// Default pdf.js URL
const _pdfjsUrl = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/$_pdfjsVersion/pdf.min.mjs';
/// Default pdf.worker.js URL
const _pdfjsWorkerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/$_pdfjsVersion/pdf.worker.min.mjs';
/// Default CMap URL
const _pdfjsCMapUrl = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/$_pdfjsVersion/cmaps/';
bool get _isPdfjsLoaded => globalContext['pdfjsLib'] != null;
@JS('pdfjsLib.getDocument')
external _PDFDocumentLoadingTask _pdfjsGetDocument(_PdfjsDocumentInitParameters data);
extension type _PdfjsDocumentInitParameters._(JSObject _) implements JSObject {
external _PdfjsDocumentInitParameters({
String? url,
JSArrayBuffer? data,
JSAny? httpHeaders,
bool? withCredentials,
String? password,
String? cMapUrl,
bool? cMapPacked,
bool? useSystemFonts,
String? standardFontDataUrl,
});
external String? get url;
external JSArrayBuffer? get data;
external JSAny? get httpHeaders;
external bool? get withCredentials;
external String? get password;
external String? get cMapUrl;
external bool? get cMapPacked;
external bool? get useSystemFonts;
external String? get standardFontDataUrl;
}
@JS('pdfjsLib.GlobalWorkerOptions.workerSrc')
external set _pdfjsWorkerSrc(String src);
extension type _PDFDocumentLoadingTask(JSObject _) implements JSObject {
external JSPromise<PdfjsDocument> get promise;
}
Future<PdfjsDocument> pdfjsGetDocument(
String url, {
String? password,
Map<String, String>? headers,
bool withCredentials = false,
}) =>
_pdfjsGetDocument(
_PdfjsDocumentInitParameters(
url: url,
password: password,
httpHeaders: headers?.jsify(),
withCredentials: withCredentials,
cMapUrl: PdfJsConfiguration.configuration?.cMapUrl ?? _pdfjsCMapUrl,
cMapPacked: PdfJsConfiguration.configuration?.cMapPacked ?? true,
useSystemFonts: PdfJsConfiguration.configuration?.useSystemFonts,
standardFontDataUrl: PdfJsConfiguration.configuration?.standardFontDataUrl,
),
).promise.toDart;
Future<PdfjsDocument> pdfjsGetDocumentFromData(ByteBuffer data, {String? password}) => _pdfjsGetDocument(
_PdfjsDocumentInitParameters(
data: data.toJS,
password: password,
cMapUrl: PdfJsConfiguration.configuration?.cMapUrl,
cMapPacked: PdfJsConfiguration.configuration?.cMapPacked,
useSystemFonts: PdfJsConfiguration.configuration?.useSystemFonts,
standardFontDataUrl: PdfJsConfiguration.configuration?.standardFontDataUrl,
),
).promise.toDart;
extension type PdfjsDocument._(JSObject _) implements JSObject {
external JSPromise<PdfjsPage> getPage(int pageNumber);
external JSPromise<JSArray<JSNumber>?> getPermissions();
external int get numPages;
external void destroy();
external JSPromise<JSNumber> getPageIndex(PdfjsRef ref);
external JSPromise<JSObject> getDestination(String id);
external JSPromise<JSArray<PdfjsOutlineNode>?> getOutline();
}
extension type PdfjsPage._(JSObject _) implements JSObject {
external PdfjsViewport getViewport(PdfjsViewportParams params);
external PdfjsRender render(PdfjsRenderContext params);
external int get pageNumber;
external int get rotate;
external JSNumber get userUnit;
external JSArray<JSNumber> get view;
external JSPromise<PdfjsTextContent> getTextContent(PdfjsGetTextContentParameters params);
external ReadableStream streamTextContent(PdfjsGetTextContentParameters params);
external JSPromise<JSArray<PdfjsAnnotation>> getAnnotations(PdfjsGetAnnotationsParameters params);
}
extension type PdfjsAnnotation._(JSObject _) implements JSObject {
external String get subtype;
external int get annotationType;
external JSArray<JSNumber> get rect;
external String? get url;
external String? get unsafeUrl;
external int get annotationFlags;
external JSAny? get dest;
}
extension type PdfjsViewportParams._(JSObject _) implements JSObject {
external PdfjsViewportParams({
double scale,
int rotation, // 0, 90, 180, 270
double offsetX,
double offsetY,
bool dontFlip,
});
external double get scale;
external set scale(double scale);
external int get rotation;
external set rotation(int rotation);
external double get offsetX;
external set offsetX(double offsetX);
external double get offsetY;
external set offsetY(double offsetY);
external bool get dontFlip;
external set dontFlip(bool dontFlip);
}
extension type PdfjsViewport(JSObject _) implements JSObject {
external JSArray<JSNumber> get viewBox;
external set viewBox(JSArray<JSNumber> viewBox);
external double get scale;
external set scale(double scale);
/// 0, 90, 180, 270
external int get rotation;
external set rotation(int rotation);
external double get offsetX;
external set offsetX(double offsetX);
external double get offsetY;
external set offsetY(double offsetY);
external bool get dontFlip;
external set dontFlip(bool dontFlip);
external double get width;
external set width(double w);
external double get height;
external set height(double h);
external JSArray<JSNumber>? get transform;
external set transform(JSArray<JSNumber>? m);
}
extension type PdfjsRenderContext._(JSObject _) implements JSObject {
external PdfjsRenderContext({
required web.CanvasRenderingContext2D canvasContext,
required PdfjsViewport viewport,
String intent,
int annotationMode,
bool renderInteractiveForms,
JSArray<JSNumber>? transform,
JSObject imageLayer,
JSObject canvasFactory,
JSObject background,
});
external web.CanvasRenderingContext2D get canvasContext;
external set canvasContext(web.CanvasRenderingContext2D ctx);
external PdfjsViewport get viewport;
external set viewport(PdfjsViewport viewport);
/// `display` or `print`
external String get intent;
external set intent(String intent);
/// DISABLE=0, ENABLE=1, ENABLE_FORMS=2, ENABLE_STORAGE=3
external int get annotationMode;
external set annotationMode(int annotationMode);
external bool get renderInteractiveForms;
external set renderInteractiveForms(bool renderInteractiveForms);
external JSArray<JSNumber>? get transform;
external set transform(JSArray<JSNumber>? transform);
external JSObject get imageLayer;
external set imageLayer(JSObject imageLayer);
external JSObject get canvasFactory;
external set canvasFactory(JSObject canvasFactory);
external JSObject get background;
external set background(JSObject background);
}
extension type PdfjsRender._(JSObject _) implements JSObject {
external JSPromise get promise;
}
extension type PdfjsGetTextContentParameters._(JSObject _) implements JSObject {
external PdfjsGetTextContentParameters({
bool includeMarkedContent,
bool disableNormalization,
});
external bool includeMarkedContent;
external bool disableNormalization;
}
extension type PdfjsTextContent._(JSObject _) implements JSObject {
/// Either [PdfjsTextItem] or [PdfjsTextMarkedContent]
external JSArray<PdfjsTextItem> get items;
external JSObject get styles;
}
extension type PdfjsTextItem._(JSObject _) implements JSObject {
external String get str;
/// Text direction: `ttb`, `ltr` or `rtl`.
external String get dir;
/// Matrix for transformation, in the form [a b c d e f], equivalent to:
/// ```
/// | a b 0 |
/// | c d 0 |
/// | e f 1 |
/// ```
///
/// Translation is performed with `[1 0 0 1 tx ty]`.
/// Scaling is performed with `[sx 0 0 sy 0 0]`.
/// See PDF Reference 1.7, 4.2.2 Common Transformations for more.
external JSArray<JSNumber> get transform;
external num get width;
external num get height;
external String get fontName;
external bool get hasEOL;
}
extension type PdfjsTextMarkedContent._(JSObject _) implements JSObject {
external String get type;
external String get id;
}
extension type PdfjsTextStyle._(JSObject _) implements JSObject {
external num get ascent;
external num get descent;
external bool get vertical;
external String get fontFamily;
}
extension type PdfjsBaseException._(JSObject _) implements JSObject {
external String get message;
external String get name;
}
extension type PdfjsPasswordException._(JSObject _) implements JSObject {
external String get message;
external String get name;
external String get code;
}
extension type PdfjsGetAnnotationsParameters._(JSObject _) implements JSObject {
external PdfjsGetAnnotationsParameters({String intent});
/// `display` or `print` or, `any`
external String get intent;
}
extension type PdfjsRef._(JSObject _) implements JSObject {
external int get num;
external int get gen;
}
extension type PdfjsAnnotationData._(JSObject _) implements JSObject {
external String get subtype;
external int get annotationType;
external JSArray<JSNumber> get rect;
external String? get url;
external String? get unsafeUrl;
external int get annotationFlags;
external JSObject? get dest;
}
extension type PdfjsOutlineNode._(JSObject _) implements JSObject {
external String get title;
external JSAny? get dest;
external JSArray<PdfjsOutlineNode> get items;
}
Object _dummyJsSyncContext = {};
bool _pdfjsInitialized = false;
Future<void> ensurePdfjsInitialized() async {
if (_pdfjsInitialized) return;
await _dummyJsSyncContext.synchronized(() async {
await _pdfjsInitialize();
});
}
Future<void> _pdfjsInitialize() async {
if (_pdfjsInitialized) return;
if (_isPdfjsLoaded) {
_pdfjsInitialized = true;
return;
}
final pdfJsSrc = PdfJsConfiguration.configuration?.pdfJsSrc ?? _pdfjsUrl;
try {
final script = web.document.createElement('script') as web.HTMLScriptElement
..type = 'text/javascript'
..charset = 'utf-8'
..async = true
..type = 'module'
..src = pdfJsSrc;
web.document.querySelector('head')!.appendChild(script);
await script.onLoad.first
.timeout(PdfJsConfiguration.configuration?.pdfJsDownloadTimeout ?? const Duration(seconds: 10));
} catch (e) {
throw StateError('Failed to load pdf.js from $pdfJsSrc: $e');
}
if (!_isPdfjsLoaded) {
throw StateError('Failed to load pdfjs');
}
_pdfjsWorkerSrc = PdfJsConfiguration.configuration?.workerSrc ?? _pdfjsWorkerSrc;
_pdfjsInitialized = true;
}
extension type ReadableStream._(JSObject _) implements JSObject {
external JSPromise cancel();
external ReadableStreamDefaultReader getReader(JSObject options);
}
extension type ReadableStreamDefaultReader._(JSObject _) implements JSObject {
external JSPromise<JSObject> cancel(JSObject reason);
external JSPromise<ReadableStreamChunk> read();
external void releaseLock();
}
extension type ReadableStreamChunk._(JSObject _) implements JSObject {
external JSObject get value;
external bool get done;
}
//FIXME: uncomment web on flutter 3.24
/// Configuration for the PDF.js library. /// Configuration for the PDF.js library.
/// ///
/// Set [PdfJsConfiguration.configuration] before using any APIs. It can be typically set in the main function. /// Set [PdfJsConfiguration.configuration] before using any APIs. It can be typically set in the main function.
......
// ignore_for_file: public_member_api_docs, sort_constructors_first
// ignore_for_file: avoid_web_libraries_in_flutter
import 'dart:async';
import 'dart:js_interop';
import 'dart:ui';
import 'package:flutter/services.dart';
import 'package:synchronized/extension.dart';
import 'package:web/web.dart' as web;
import '../../pdfrx.dart';
import 'pdf.js.dart';
class PdfDocumentFactoryImpl extends PdfDocumentFactory {
@override
Future<PdfDocument> openAsset(
String name, {
PdfPasswordProvider? passwordProvider,
bool firstAttemptByEmptyPassword = true,
}) =>
_openByFunc(
(password) async {
// NOTE: Moving the asset load outside the loop may cause:
// Uncaught TypeError: Cannot perform Construct on a detached ArrayBuffer
final bytes = await rootBundle.load(name);
return await pdfjsGetDocumentFromData(bytes.buffer, password: password);
},
sourceName: 'asset:$name',
passwordProvider: passwordProvider,
firstAttemptByEmptyPassword: firstAttemptByEmptyPassword,
);
@override
Future<PdfDocument> openCustom({
required FutureOr<int> Function(Uint8List buffer, int position, int size) read,
required int fileSize,
required String sourceName,
PdfPasswordProvider? passwordProvider,
bool firstAttemptByEmptyPassword = true,
int? maxSizeToCacheOnMemory,
void Function()? onDispose,
}) async {
final buffer = Uint8List(fileSize);
await read(buffer, 0, fileSize);
return _openByFunc(
(password) => pdfjsGetDocumentFromData(
buffer.buffer,
password: password,
),
sourceName: sourceName,
passwordProvider: passwordProvider,
firstAttemptByEmptyPassword: firstAttemptByEmptyPassword,
onDispose: onDispose,
);
}
@override
Future<PdfDocument> openData(
Uint8List data, {
PdfPasswordProvider? passwordProvider,
bool firstAttemptByEmptyPassword = true,
String? sourceName,
void Function()? onDispose,
}) async {
return _openByFunc(
(password) => pdfjsGetDocumentFromData(
data.buffer,
password: password,
),
sourceName: sourceName ?? 'memory-${data.hashCode}',
passwordProvider: passwordProvider,
firstAttemptByEmptyPassword: firstAttemptByEmptyPassword,
onDispose: onDispose,
);
}
@override
Future<PdfDocument> openFile(
String filePath, {
PdfPasswordProvider? passwordProvider,
bool firstAttemptByEmptyPassword = true,
}) =>
_openByFunc(
(password) => pdfjsGetDocument(
filePath,
password: password,
),
sourceName: filePath,
passwordProvider: passwordProvider,
firstAttemptByEmptyPassword: firstAttemptByEmptyPassword,
);
@override
Future<PdfDocument> openUri(
Uri uri, {
PdfPasswordProvider? passwordProvider,
bool firstAttemptByEmptyPassword = true,
PdfDownloadProgressCallback? progressCallback,
PdfDownloadReportCallback? reportCallback,
bool preferRangeAccess = false,
Map<String, String>? headers,
bool withCredentials = false,
}) =>
_openByFunc(
(password) => pdfjsGetDocument(
uri.toString(),
password: password,
headers: headers,
withCredentials: withCredentials,
),
sourceName: uri.toString(),
passwordProvider: passwordProvider,
firstAttemptByEmptyPassword: firstAttemptByEmptyPassword,
);
Future<PdfDocument> _openByFunc(
Future<PdfjsDocument> Function(String? password) openDocument, {
required String sourceName,
PdfPasswordProvider? passwordProvider,
bool firstAttemptByEmptyPassword = true,
void Function()? onDispose,
}) async {
for (int i = 0;; i++) {
final String? password;
if (firstAttemptByEmptyPassword && i == 0) {
password = null;
} else {
password = await passwordProvider?.call();
if (password == null) {
throw const PdfPasswordException('No password supplied by PasswordProvider.');
}
}
try {
await ensurePdfjsInitialized();
return PdfDocumentWeb.fromDocument(
await openDocument(password),
sourceName: sourceName,
onDispose: onDispose,
);
} catch (e) {
if (!_isPasswordError(e)) {
rethrow;
}
}
}
}
static bool _isPasswordError(dynamic e) => e.toString().startsWith('PasswordException:');
}
class PdfDocumentWeb extends PdfDocument {
PdfDocumentWeb._(
this._document, {
required super.sourceName,
required this.isEncrypted,
required this.permissions,
this.onDispose,
});
@override
final bool isEncrypted;
@override
final PdfPermissions? permissions;
final PdfjsDocument _document;
final void Function()? onDispose;
static Future<PdfDocumentWeb> fromDocument(
PdfjsDocument document, {
required String sourceName,
void Function()? onDispose,
}) async {
final perms = (await document.getPermissions().toDart)?.toDart.cast<int>();
final doc = PdfDocumentWeb._(
document,
sourceName: sourceName,
isEncrypted: perms != null,
permissions: perms != null ? PdfPermissions(perms.fold<int>(0, (p, e) => p | e), 2) : null,
onDispose: onDispose,
);
final pageCount = document.numPages;
final pages = <PdfPage>[];
for (int i = 0; i < pageCount; i++) {
pages.add(await doc._getPage(document, i + 1));
}
doc.pages = List.unmodifiable(pages);
return doc;
}
@override
Future<void> dispose() async {
_document.destroy();
onDispose?.call();
}
Future<PdfPage> _getPage(PdfjsDocument document, int pageNumber) async {
final page = await _document.getPage(pageNumber).toDart;
final vp1 = page.getViewport(PdfjsViewportParams(scale: 1));
return PdfPageWeb._(
document: this,
pageNumber: pageNumber,
page: page,
width: vp1.width,
height: vp1.height,
rotation: PdfPageRotation.values[page.rotate ~/ 90]);
}
@override
late final List<PdfPage> pages;
@override
bool isIdenticalDocumentHandle(Object? other) => other is PdfDocumentWeb && _document == other._document;
Future<JSObject?> _getDestObject(JSAny? dest) async {
if (dest == null) return null;
if (dest is String) {
final destObj = await _document.getDestination(dest as String).toDart;
return destObj;
} else {
return dest as JSObject;
}
}
@override
Future<List<PdfOutlineNode>> loadOutline() async {
final outline = await _document.getOutline().toDart;
if (outline == null) return [];
final nodes = <PdfOutlineNode>[];
for (final node in outline.toDart) {
nodes.add(await _pdfOutlineNodeFromOutline(node));
}
return nodes;
}
Future<PdfOutlineNode> _pdfOutlineNodeFromOutline(PdfjsOutlineNode outline) async {
final children = <PdfOutlineNode>[];
for (final item in outline.items.toDart) {
children.add(await _pdfOutlineNodeFromOutline(item));
}
return PdfOutlineNode(
title: outline.title,
dest: await _getDestination(outline.dest),
children: children,
);
}
/// NOTE: The returned [PdfDest] is always compacted.
Future<PdfDest?> _getDestination(JSAny? dest) async {
final destObj = await _getDestObject(dest);
if (destObj is! JSArray) return null;
final arr = destObj.toDart;
final ref = arr[0] as PdfjsRef;
final cmdStr = _getName(arr[1]);
final params = arr.length < 3 ? null : List<double?>.unmodifiable(arr.sublist(2).cast<double?>());
return PdfDest(
(await _document.getPageIndex(ref).toDart).toDartInt + 1,
_parseCmdStr(cmdStr),
params,
);
}
static PdfDestCommand _parseCmdStr(String cmdStr) {
switch (cmdStr) {
case 'XYZ':
return PdfDestCommand.xyz;
case 'Fit':
return PdfDestCommand.fit;
case 'FitB':
return PdfDestCommand.fitB;
case 'FitH':
return PdfDestCommand.fitH;
case 'FitBH':
return PdfDestCommand.fitBH;
case 'FitV':
return PdfDestCommand.fitV;
case 'FitBV':
return PdfDestCommand.fitBV;
case 'FitR':
return PdfDestCommand.fitR;
default:
return PdfDestCommand.unknown;
}
}
static String _getName(JSAny? name) {
final obj = name.dartify();
if (obj is Map) {
return obj['name'].toString();
} else {
return obj.toString();
}
}
}
class PdfPageWeb extends PdfPage {
PdfPageWeb._({
required this.document,
required this.pageNumber,
required this.page,
required this.width,
required this.height,
required this.rotation,
});
@override
final PdfDocumentWeb document;
@override
final int pageNumber;
final PdfjsPage page;
@override
final double width;
@override
final double height;
@override
final PdfPageRotation rotation;
@override
Future<PdfImage?> render({
int x = 0,
int y = 0,
int? width,
int? height,
double? fullWidth,
double? fullHeight,
Color? backgroundColor,
PdfAnnotationRenderingMode annotationRenderingMode = PdfAnnotationRenderingMode.annotationAndForms,
PdfPageRenderCancellationToken? cancellationToken,
}) async {
if (cancellationToken != null && cancellationToken is! PdfPageRenderCancellationTokenWeb) {
throw ArgumentError(
'cancellationToken must be created by PdfPage.createCancellationToken().',
'cancellationToken',
);
}
fullWidth ??= this.width;
fullHeight ??= this.height;
width ??= fullWidth.toInt();
height ??= fullHeight.toInt();
return await synchronized(() async {
if (cancellationToken is PdfPageRenderCancellationTokenWeb && cancellationToken.isCanceled == true) {
return null;
}
final data = await _renderRaw(
x,
y,
width!,
height!,
fullWidth!,
fullHeight!,
backgroundColor,
false,
annotationRenderingMode,
);
return PdfImageWeb(
width: width,
height: height,
pixels: data,
);
});
}
@override
PdfPageRenderCancellationTokenWeb createCancellationToken() => PdfPageRenderCancellationTokenWeb();
Future<Uint8List> _renderRaw(
int x,
int y,
int width,
int height,
double fullWidth,
double fullHeight,
Color? backgroundColor,
bool dontFlip,
PdfAnnotationRenderingMode annotationRenderingMode,
) async {
final vp1 = page.getViewport(PdfjsViewportParams(scale: 1));
final pageWidth = vp1.width;
if (width <= 0 || height <= 0) {
throw PdfException('Invalid PDF page rendering rectangle ($width x $height)');
}
final vp = page.getViewport(PdfjsViewportParams(
scale: fullWidth / pageWidth, offsetX: -x.toDouble(), offsetY: -y.toDouble(), dontFlip: dontFlip));
final canvas = web.document.createElement('canvas') as web.HTMLCanvasElement;
canvas.width = width;
canvas.height = height;
if (backgroundColor != null) {
canvas.context2D.fillStyle = '#${backgroundColor.value.toRadixString(16).padLeft(8, '0')}'.toJS;
canvas.context2D.fillRect(0, 0, width, height);
}
await page
.render(
PdfjsRenderContext(
canvasContext: canvas.context2D,
viewport: vp,
annotationMode: annotationRenderingMode.index,
),
)
.promise
.toDart;
final src = canvas.context2D.getImageData(0, 0, width, height).data.toDart.buffer.asUint8List();
return src;
}
@override
Future<PdfPageText> loadText() => PdfPageTextWeb._loadText(this);
@override
Future<List<PdfLink>> loadLinks({bool compact = false}) async {
final annots = (await page.getAnnotations(PdfjsGetAnnotationsParameters()).toDart).toDart;
final links = <PdfLink>[];
for (final annot in annots) {
if (annot.subtype != 'Link') {
continue;
}
final rect = annot.rect.toDart.cast<double>();
final rects = List<PdfRect>.unmodifiable([PdfRect(rect[0], rect[3], rect[2], rect[1])]);
if (annot.url != null) {
links.add(
PdfLink(rects, url: Uri.parse(annot.url!)),
);
continue;
}
final dest = await document._getDestination(annot.dest);
if (dest != null) {
links.add(
PdfLink(rects, dest: dest),
);
continue;
}
}
return compact ? List.unmodifiable(links) : links;
}
}
class PdfPageRenderCancellationTokenWeb extends PdfPageRenderCancellationToken {
bool _canceled = false;
@override
void cancel() => _canceled = true;
@override
bool get isCanceled => _canceled;
}
class PdfImageWeb extends PdfImage {
PdfImageWeb({required this.width, required this.height, required this.pixels});
@override
final int width;
@override
final int height;
@override
final Uint8List pixels;
@override
PixelFormat get format => PixelFormat.rgba8888;
@override
void dispose() {}
}
class PdfPageTextFragmentWeb implements PdfPageTextFragment {
PdfPageTextFragmentWeb(this.index, this.bounds, this.text);
@override
final int index;
@override
int get length => text.length;
@override
int get end => index + length;
@override
final PdfRect bounds;
@override
List<PdfRect>? get charRects => null;
@override
final String text;
}
class PdfPageTextWeb extends PdfPageText {
PdfPageTextWeb({
required this.pageNumber,
required this.fullText,
required this.fragments,
});
@override
final int pageNumber;
@override
final String fullText;
@override
final List<PdfPageTextFragment> fragments;
static Future<PdfPageTextWeb> _loadText(PdfPageWeb page) async {
final content = await page.page
.getTextContent(
PdfjsGetTextContentParameters(
includeMarkedContent: false,
disableNormalization: false,
),
)
.toDart;
final sb = StringBuffer();
final fragments = <PdfPageTextFragmentWeb>[];
for (final item in content.items.toDart) {
final t = item.transform.toDart.cast<double>();
final x = t[4];
final y = t[5];
final str = item.hasEOL ? '${item.str}\n' : item.str;
if (str == '\n' && fragments.isNotEmpty) {
final prev = fragments.last;
fragments.add(
PdfPageTextFragmentWeb(
sb.length,
PdfRect(
prev.bounds.right,
prev.bounds.top,
prev.bounds.right + item.width.toDouble(),
prev.bounds.bottom,
),
str,
),
);
} else {
fragments.add(
PdfPageTextFragmentWeb(
sb.length,
PdfRect(
x,
y + item.height.toDouble(),
x + item.width.toDouble(),
y,
),
str,
),
);
}
sb.write(str);
}
return PdfPageTextWeb(pageNumber: page.pageNumber, fullText: sb.toString(), fragments: fragments);
}
}
...@@ -189,6 +189,7 @@ class _PdfTextRenderBox extends RenderBox with Selectable, SelectionRegistrant { ...@@ -189,6 +189,7 @@ class _PdfTextRenderBox extends RenderBox with Selectable, SelectionRegistrant {
PdfPage get _page => _textWidget._state.widget.page; PdfPage get _page => _textWidget._state.widget.page;
List<PdfPageTextFragment> get _fragments => _textWidget._state.fragments!; List<PdfPageTextFragment> get _fragments => _textWidget._state.fragments!;
@override
List<Rect> get boundingBoxes => <Rect>[paintBounds]; List<Rect> get boundingBoxes => <Rect>[paintBounds];
@override @override
......
...@@ -244,7 +244,7 @@ class PdfTextSearcher extends Listenable { ...@@ -244,7 +244,7 @@ class PdfTextSearcher extends Listenable {
/// Paint callback to highlight the matches. /// Paint callback to highlight the matches.
/// ///
/// Use this with PdfViewerParams.pagePaintCallback to highlight the matches. /// Use this with [PdfViewerParams.pagePaintCallback] to highlight the matches.
void pageTextMatchPaintCallback(ui.Canvas canvas, Rect pageRect, PdfPage page) { void pageTextMatchPaintCallback(ui.Canvas canvas, Rect pageRect, PdfPage page) {
final range = getMatchesRangeForPage(page.pageNumber); final range = getMatchesRangeForPage(page.pageNumber);
if (range == null) return; if (range == null) return;
......
// SPDX-FileCopyrightText: Copyright 2018 @espresso3389 (Takashi Kawasaki)
// SPDX-FileCopyrightText: Copyright 2024 Noname_1111788
// SPDX-FileCopyrightText: Copyright 2024 Open Mobile Platform LLC <community@omp.ru>
// SPDX-License-Identifier: BSD-3-Clause
// ignore_for_file: public_member_api_docs // ignore_for_file: public_member_api_docs
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
...@@ -455,9 +450,8 @@ class _PdfViewerState extends State<PdfViewer> with SingleTickerProviderStateMix ...@@ -455,9 +450,8 @@ class _PdfViewerState extends State<PdfViewer> with SingleTickerProviderStateMix
/// Key pressing state of ⌘ or Control depending on the platform. /// Key pressing state of ⌘ or Control depending on the platform.
static bool get _isCommandKeyPressed => Platform.isMacOS || Platform.isIOS static bool get _isCommandKeyPressed => Platform.isMacOS || Platform.isIOS
? RawKeyboard.instance.keysPressed.contains(LogicalKeyboardKey.meta) //HardwareKeyboard.instance.isMetaPressed ? HardwareKeyboard.instance.isMetaPressed
: RawKeyboard.instance.keysPressed : HardwareKeyboard.instance.isControlPressed;
.contains(LogicalKeyboardKey.control); //HardwareKeyboard.instance.isControlPressed;
KeyEventResult _onKeyEvent(FocusNode node, KeyEvent event) { KeyEventResult _onKeyEvent(FocusNode node, KeyEvent event) {
final isDown = event is KeyDownEvent; final isDown = event is KeyDownEvent;
......
...@@ -9,7 +9,7 @@ version: 1.0.82 ...@@ -9,7 +9,7 @@ version: 1.0.82
publish_to: "none" publish_to: "none"
environment: environment:
sdk: ">=3.2.2 <4.0.0" sdk: ">=3.3.0 <4.0.0"
flutter: ">=3.16.0" flutter: ">=3.16.0"
dependencies: dependencies:
...@@ -33,7 +33,7 @@ dependencies: ...@@ -33,7 +33,7 @@ dependencies:
url: https://gitlab.com/omprussia/flutter/packages.git url: https://gitlab.com/omprussia/flutter/packages.git
path: packages/url_launcher_aurora path: packages/url_launcher_aurora
vector_math: ^2.1.4 vector_math: ^2.1.4
web: ^0.3.0 web: ^0.5.1
package_info_plus: ^4.1.0 package_info_plus: ^4.1.0
package_info_plus_aurora: package_info_plus_aurora:
git: git:
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать