David PHAM-VAN

Add Linux platform

... ... @@ -13,7 +13,7 @@
# limitations under the License.
DART_SRC=$(shell find . -name '*.dart')
CLNG_SRC=$(shell find printing/ios printing/macos printing/windows printing/android -name '*.cpp' -o -name '*.m' -o -name '*.h' -o -name '*.java')
CLNG_SRC=$(shell find printing/ios printing/macos printing/windows printing/linux printing/android -name '*.cpp' -o -name '*.cc' -o -name '*.m' -o -name '*.h' -o -name '*.java')
SWFT_SRC=$(shell find printing/ios printing/macos -name '*.swift')
FONTS=pdf/open-sans.ttf pdf/open-sans-bold.ttf pdf/roboto.ttf pdf/noto-sans.ttf pdf/genyomintw.ttf demo/assets/roboto1.ttf demo/assets/roboto2.ttf demo/assets/roboto3.ttf demo/assets/open-sans.ttf demo/assets/open-sans-bold.ttf pdf/hacen-tunisia.ttf pdf/material.ttf demo/assets/material.ttf
COV_PORT=9292
... ...
... ... @@ -39,3 +39,4 @@ macos/Podfile.lock
assets/*.png
assets/*.jpg
assets/logo.svg
linux
... ...
... ... @@ -8,6 +8,7 @@
- Improve orientation handling
- Improve directPrint
- Remove the windows DLL
- Add Linux platform
## 3.7.2
... ...
... ... @@ -51,3 +51,4 @@ web
README.md
test
windows
linux
... ...
# Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
#
# 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.
cmake_minimum_required(VERSION 3.10)
set(PROJECT_NAME "printing")
project(${PROJECT_NAME} LANGUAGES CXX)
# Download pdfium
include(../windows/DownloadProject.cmake)
download_project(
PROJ
pdfium
URL
https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-linux.tgz
)
# This value is used when generating builds using this plugin, so it must not be
# changed
set(PLUGIN_NAME "printing_plugin")
include(${pdfium_SOURCE_DIR}/PDFiumConfig.cmake)
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTKUnixPrint REQUIRED IMPORTED_TARGET gtk+-unix-print-3.0)
add_library(${PLUGIN_NAME} SHARED
"printing_plugin.cc"
"include/printing/printing_plugin.h"
"print_job.cc"
"print_job.h"
)
apply_standard_settings(${PLUGIN_NAME})
set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden)
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
target_include_directories(${PLUGIN_NAME}
INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK PkgConfig::GTKUnixPrint)
target_link_libraries(${PLUGIN_NAME} PRIVATE pdfium)
# List of absolute paths to libraries that should be bundled with the plugin
set(printing_bundled_libraries
"${PDFium_LIBRARY}"
PARENT_SCOPE)
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* 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.
*/
#ifndef FLUTTER_PLUGIN_PRINTING_PLUGIN_H_
#define FLUTTER_PLUGIN_PRINTING_PLUGIN_H_
#include <flutter_linux/flutter_linux.h>
G_BEGIN_DECLS
#ifdef FLUTTER_PLUGIN_IMPL
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
#else
#define FLUTTER_PLUGIN_EXPORT
#endif
typedef struct _PrintingPlugin PrintingPlugin;
typedef struct {
GObjectClass parent_class;
} PrintingPluginClass;
FLUTTER_PLUGIN_EXPORT GType printing_plugin_get_type();
FLUTTER_PLUGIN_EXPORT void printing_plugin_register_with_registrar(
FlPluginRegistrar* registrar);
G_END_DECLS
#endif // FLUTTER_PLUGIN_PRINTING_PLUGIN_H_
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* 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.
*/
#include "print_job.h"
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <fpdfview.h>
print_job::print_job(int index) : index(index) {}
print_job::~print_job() {}
static gboolean add_printer(GtkPrinter* printer, gpointer data) {
auto printers = static_cast<FlValue*>(data);
auto map = fl_value_new_map();
auto name = gtk_printer_get_name(printer);
auto loc = gtk_printer_get_location(printer);
auto cmt = gtk_printer_get_description(printer);
fl_value_set_string(map, "url", fl_value_new_string(name));
fl_value_set_string(map, "name", fl_value_new_string(name));
if (loc) {
fl_value_set_string(map, "location", fl_value_new_string(loc));
}
if (cmt) {
fl_value_set_string(map, "comment", fl_value_new_string(cmt));
}
fl_value_set_string(map, "default",
fl_value_new_bool(gtk_printer_is_default(printer)));
fl_value_set_string(map, "available",
fl_value_new_bool(gtk_printer_is_active(printer) &&
gtk_printer_accepts_pdf(printer)));
fl_value_append(printers, map);
return false;
}
FlValue* print_job::list_printers() {
auto printers = fl_value_new_list();
gtk_enumerate_printers(add_printer, printers, nullptr, true);
return printers;
}
static GtkPrinter* _printer;
static gboolean search_printer(GtkPrinter* printer, gpointer data) {
auto search = static_cast<gchar*>(data);
auto name = gtk_printer_get_name(printer);
if (strcmp(name, search) == 0) {
_printer = static_cast<GtkPrinter*>(g_object_ref(printer));
return true;
}
return false;
}
bool print_job::direct_print_pdf(const gchar* name,
const uint8_t data[],
size_t size,
const gchar* printer) {
_printer = nullptr;
auto pname = strdup(printer);
gtk_enumerate_printers(search_printer, pname, nullptr, true);
free(pname);
if (!_printer) {
return false;
}
auto settings = gtk_print_settings_new();
auto setup = gtk_page_setup_new();
printJob = gtk_print_job_new(name, _printer, settings, setup);
this->write_job(data, size);
g_object_unref(_printer);
g_object_unref(settings);
g_object_unref(setup);
g_object_unref(printJob);
return true;
}
static void job_completed(GtkPrintJob* gtk_print_job,
gpointer user_data,
const GError* error) {
auto job = static_cast<print_job*>(user_data);
on_completed(job, error == nullptr,
error != nullptr ? error->message : nullptr);
}
bool print_job::print_pdf(const gchar* name,
double pageWidth,
double pageHeight,
double marginLeft,
double marginTop,
double marginRight,
double marginBottom) {
documentName = strdup(name);
auto dialog =
GTK_PRINT_UNIX_DIALOG(gtk_print_unix_dialog_new(documentName, nullptr));
gtk_print_unix_dialog_set_manual_capabilities(
dialog, (GtkPrintCapabilities)(GTK_PRINT_CAPABILITY_GENERATE_PDF));
gtk_widget_realize(GTK_WIDGET(dialog));
auto response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_hide(GTK_WIDGET(dialog));
switch (response) {
case GTK_RESPONSE_OK: {
GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(
GTK_PRINT_UNIX_DIALOG(dialog));
if (!gtk_printer_accepts_pdf(printer)) {
on_completed(this, false, "This printer does not accept PDF jobs");
break;
}
GtkPrintSettings* settings =
gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog));
GtkPageSetup* setup =
gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog));
auto width = gtk_page_setup_get_page_width(setup, GTK_UNIT_POINTS);
auto height = gtk_page_setup_get_page_height(setup, GTK_UNIT_POINTS);
auto marginLeft = gtk_page_setup_get_left_margin(setup, GTK_UNIT_POINTS);
auto marginTop = gtk_page_setup_get_top_margin(setup, GTK_UNIT_POINTS);
auto marginRight =
gtk_page_setup_get_right_margin(setup, GTK_UNIT_POINTS);
auto marginBottom =
gtk_page_setup_get_bottom_margin(setup, GTK_UNIT_POINTS);
printJob = gtk_print_job_new(name, printer, settings, setup);
on_layout(this, width, height, marginLeft, marginTop, marginRight,
marginBottom);
g_object_unref(settings);
gtk_widget_destroy(GTK_WIDGET(dialog));
return true;
}
case GTK_RESPONSE_DELETE_EVENT: // Fall through.
case GTK_RESPONSE_CANCEL: // Cancel
case GTK_RESPONSE_APPLY: // Preview
break;
}
gtk_widget_destroy(GTK_WIDGET(dialog));
on_completed(this, false, nullptr);
return true;
}
void print_job::write_job(const uint8_t data[], size_t size) {
auto fd = memfd_create("printing", 0);
size_t offset = 0;
size_t n;
while ((n = write(fd, data + offset, size - offset)) >= 0 &&
size - offset > 0) {
offset += n;
}
if (n < 0) {
on_completed(this, false, "Unable to copy the PDF data");
}
lseek(fd, 0, SEEK_SET);
gtk_print_job_set_source_fd(printJob, fd, nullptr);
gtk_print_job_send(printJob, job_completed, this, nullptr);
}
void print_job::cancel_job(const gchar* error) {}
bool print_job::share_pdf(const uint8_t data[],
size_t size,
const gchar* name) {
auto filename = "/tmp/" + std::string(name);
auto fd = fopen(filename.c_str(), "wb");
fwrite(data, size, 1, fd);
fclose(fd);
auto pid = fork();
if (pid < 0) { // error occurred
return false;
} else if (pid == 0) { // child process
execlp("xdg-open", "xdg-open", filename.c_str(), nullptr);
}
int status = 0;
waitpid(pid, &status, 0);
return status == 0;
}
void print_job::raster_pdf(const uint8_t data[],
size_t size,
const int32_t pages[],
size_t pages_count,
double scale) {
FPDF_InitLibraryWithConfig(nullptr);
auto doc = FPDF_LoadMemDocument64(data, size, nullptr);
if (!doc) {
FPDF_DestroyLibrary();
on_page_raster_end(this);
return;
}
auto pageCount = FPDF_GetPageCount(doc);
auto allPages = false;
if (pages_count == 0) {
allPages = true;
pages_count = pageCount;
}
for (auto pn = 0; pn < pages_count; pn++) {
auto n = allPages ? pn : pages[pn];
if (n >= pageCount) {
continue;
}
auto page = FPDF_LoadPage(doc, n);
if (!page) {
continue;
}
auto width = FPDF_GetPageWidth(page);
auto height = FPDF_GetPageHeight(page);
auto bWidth = static_cast<int>(width * scale);
auto bHeight = static_cast<int>(height * scale);
auto bitmap = FPDFBitmap_Create(bWidth, bHeight, 0);
FPDFBitmap_FillRect(bitmap, 0, 0, bWidth, bHeight, 0xffffffff);
FPDF_RenderPageBitmap(bitmap, page, 0, 0, bWidth, bHeight, 0, FPDF_ANNOT);
uint8_t* p = static_cast<uint8_t*>(FPDFBitmap_GetBuffer(bitmap));
auto stride = FPDFBitmap_GetStride(bitmap);
size_t l = static_cast<size_t>(bHeight * stride);
// BGRA to RGBA conversion
for (auto y = 0; y < bHeight; y++) {
auto offset = y * stride;
for (auto x = 0; x < bWidth; x++) {
auto t = p[offset];
p[offset] = p[offset + 2];
p[offset + 2] = t;
offset += 4;
}
}
on_page_rasterized(this, p, l, bWidth, bHeight);
FPDFBitmap_Destroy(bitmap);
}
FPDF_CloseDocument(doc);
FPDF_DestroyLibrary();
on_page_raster_end(this);
}
FlValue* print_job::printing_info() {
FlValue* result = fl_value_new_map();
fl_value_set_string(result, "canPrint", fl_value_new_bool(true));
fl_value_set_string(result, "canShare", fl_value_new_bool(true));
fl_value_set_string(result, "canRaster", fl_value_new_bool(true));
fl_value_set_string(result, "canListPrinters", fl_value_new_bool(true));
fl_value_set_string(result, "directPrint", fl_value_new_bool(true));
fl_value_set_string(result, "dynamicLayout", fl_value_new_bool(true));
return result;
}
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* 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.
*/
#ifndef PRINTING_PLUGIN_PRINT_JOB_H_
#define PRINTING_PLUGIN_PRINT_JOB_H_
#include <flutter_linux/flutter_linux.h>
#include <gtk/gtk.h>
#include <gtk/gtkunixprint.h>
class print_job {
private:
const int index;
char* documentName = nullptr;
GtkPrintJob* printJob;
public:
print_job(int index);
~print_job();
int get_id() { return index; };
static FlValue* list_printers();
bool direct_print_pdf(const gchar* name,
const uint8_t data[],
size_t size,
const gchar* printer);
bool print_pdf(const gchar* name,
double pageWidth,
double pageHeight,
double marginLeft,
double marginTop,
double marginRight,
double marginBottom);
void write_job(const uint8_t data[], size_t size);
void cancel_job(const gchar* error);
static bool share_pdf(const uint8_t data[], size_t size, const gchar* name);
void raster_pdf(const uint8_t data[],
size_t size,
const int32_t pages[],
size_t pages_count,
double scale);
static FlValue* printing_info();
};
void on_page_rasterized(print_job* job,
const uint8_t* data,
size_t size,
int width,
int height);
void on_page_raster_end(print_job* job);
void on_layout(print_job* job,
double pageWidth,
double pageHeight,
double marginLeft,
double marginTop,
double marginRight,
double marginBottom);
void on_completed(print_job* job, bool completed, const char* error);
#endif // PRINTING_PLUGIN_PRINT_JOB_H_
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* 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.
*/
#include "include/printing/printing_plugin.h"
#include <memory>
#include <flutter_linux/flutter_linux.h>
#include <gtk/gtk.h>
#include "print_job.h"
#define PRINTING_PLUGIN(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), printing_plugin_get_type(), \
PrintingPlugin))
struct _PrintingPlugin {
GObject parent_instance;
};
G_DEFINE_TYPE(PrintingPlugin, printing_plugin, g_object_get_type())
static FlMethodChannel* channel;
// Called when a method call is received from Flutter.
static void printing_plugin_handle_method_call(PrintingPlugin* self,
FlMethodCall* method_call) {
g_autoptr(FlMethodResponse) response = nullptr;
const gchar* method = fl_method_call_get_name(method_call);
FlValue* args = fl_method_call_get_args(method_call);
if (strcmp(method, "printingInfo") == 0) {
g_autoptr(FlValue) result = print_job::printing_info();
response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
} else if (strcmp(method, "listPrinters") == 0) {
g_autoptr(FlValue) result = print_job::list_printers();
response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
} else if (strcmp(method, "printPdf") == 0) {
auto name = fl_value_get_string(fl_value_lookup_string(args, "name"));
auto jobNum = fl_value_get_int(fl_value_lookup_string(args, "job"));
auto pageWidth = fl_value_get_float(fl_value_lookup_string(args, "width"));
auto pageHeight =
fl_value_get_float(fl_value_lookup_string(args, "height"));
auto marginLeft =
fl_value_get_float(fl_value_lookup_string(args, "marginLeft"));
auto marginTop =
fl_value_get_float(fl_value_lookup_string(args, "marginTop"));
auto marginRight =
fl_value_get_float(fl_value_lookup_string(args, "marginRight"));
auto marginBottom =
fl_value_get_float(fl_value_lookup_string(args, "marginBottom"));
auto job = new print_job(jobNum);
auto res = job->print_pdf(name, pageWidth, pageHeight, marginLeft,
marginTop, marginRight, marginBottom);
if (!res) {
delete job;
}
g_autoptr(FlValue) result = fl_value_new_int(res);
response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
} else if (strcmp(method, "directPrintPdf") == 0) {
auto jobNum = fl_value_get_int(fl_value_lookup_string(args, "job"));
auto name = fl_value_get_string(fl_value_lookup_string(args, "name"));
auto printer = fl_value_get_string(fl_value_lookup_string(args, "printer"));
auto doc = fl_value_get_uint8_list(fl_value_lookup_string(args, "doc"));
auto size = fl_value_get_length(fl_value_lookup_string(args, "doc"));
auto job = std::make_unique<print_job>(jobNum);
auto res = job->direct_print_pdf(name, doc, size, printer);
g_autoptr(FlValue) result = fl_value_new_int(res);
response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
} else if (strcmp(method, "sharePdf") == 0) {
auto name = fl_value_get_string(fl_value_lookup_string(args, "name"));
auto doc = fl_value_get_uint8_list(fl_value_lookup_string(args, "doc"));
auto size = fl_value_get_length(fl_value_lookup_string(args, "doc"));
auto res = print_job::share_pdf(doc, size, name);
g_autoptr(FlValue) result = fl_value_new_int(res);
response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
} else if (strcmp(method, "rasterPdf") == 0) {
auto doc = fl_value_get_uint8_list(fl_value_lookup_string(args, "doc"));
auto size = fl_value_get_length(fl_value_lookup_string(args, "doc"));
auto v_pages = fl_value_lookup_string(args, "pages");
int32_t* pages = nullptr;
size_t pages_count = 0;
if (fl_value_get_type(v_pages) == FL_VALUE_TYPE_LIST) {
pages_count = fl_value_get_length(v_pages);
pages = (int32_t*)malloc(sizeof(int32_t) * pages_count);
for (auto n = 0; n < pages_count; n++) {
pages[n] = fl_value_get_int(fl_value_get_list_value(v_pages, n));
}
}
auto scale = fl_value_get_float(fl_value_lookup_string(args, "scale"));
auto jobNum = fl_value_get_int(fl_value_lookup_string(args, "job"));
auto job = std::make_unique<print_job>(jobNum);
job->raster_pdf(doc, size, pages, pages_count, scale);
free(pages);
g_autoptr(FlValue) result = fl_value_new_bool(true);
response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
} else {
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
}
fl_method_call_respond(method_call, response, nullptr);
}
static void printing_plugin_dispose(GObject* object) {
G_OBJECT_CLASS(printing_plugin_parent_class)->dispose(object);
}
static void printing_plugin_class_init(PrintingPluginClass* klass) {
G_OBJECT_CLASS(klass)->dispose = printing_plugin_dispose;
}
static void printing_plugin_init(PrintingPlugin* self) {}
static void method_call_cb(FlMethodChannel* channel,
FlMethodCall* method_call,
gpointer user_data) {
PrintingPlugin* plugin = PRINTING_PLUGIN(user_data);
printing_plugin_handle_method_call(plugin, method_call);
}
void printing_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
PrintingPlugin* plugin =
PRINTING_PLUGIN(g_object_new(printing_plugin_get_type(), nullptr));
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
channel = fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
"net.nfet.printing", FL_METHOD_CODEC(codec));
fl_method_channel_set_method_call_handler(
channel, method_call_cb, g_object_ref(plugin), g_object_unref);
g_object_unref(plugin);
}
void on_page_rasterized(print_job* job,
const uint8_t* data,
size_t size,
int width,
int height) {
g_autoptr(FlValue) map = fl_value_new_map();
fl_value_set_string(map, "image", fl_value_new_uint8_list(data, size));
fl_value_set_string(map, "width", fl_value_new_int(width));
fl_value_set_string(map, "height", fl_value_new_int(height));
fl_value_set_string(map, "job", fl_value_new_int(job->get_id()));
fl_method_channel_invoke_method(channel, "onPageRasterized", map, nullptr,
nullptr, nullptr);
}
void on_page_raster_end(print_job* job) {
g_autoptr(FlValue) map = fl_value_new_map();
fl_value_set_string(map, "job", fl_value_new_int(job->get_id()));
fl_method_channel_invoke_method(channel, "onPageRasterEnd", map, nullptr,
nullptr, nullptr);
}
static void on_layout_response_cb(GObject* object,
GAsyncResult* result,
gpointer user_data) {
print_job* job = static_cast<print_job*>(user_data);
g_autoptr(GError) error = nullptr;
g_autoptr(FlMethodResponse) response =
fl_method_channel_invoke_method_finish(channel, result, &error);
if (!response) {
job->cancel_job(error->message);
}
if (FL_IS_METHOD_SUCCESS_RESPONSE(response)) {
FlValue* result = fl_method_success_response_get_result(
FL_METHOD_SUCCESS_RESPONSE(response));
auto data = fl_value_get_uint8_list(result);
auto size = fl_value_get_length(result);
job->write_job(data, size);
} else if (FL_IS_METHOD_ERROR_RESPONSE(response)) {
FlMethodErrorResponse* error_response = FL_METHOD_ERROR_RESPONSE(response);
// fl_method_error_response_get_code(error_response);
auto message = fl_method_error_response_get_message(error_response);
// fl_method_error_response_get_details(error_response);
job->cancel_job(message);
}
}
void on_layout(print_job* job,
double pageWidth,
double pageHeight,
double marginLeft,
double marginTop,
double marginRight,
double marginBottom) {
g_autoptr(FlValue) map = fl_value_new_map();
fl_value_set_string(map, "job", fl_value_new_int(job->get_id()));
fl_value_set_string(map, "width", fl_value_new_float(pageWidth));
fl_value_set_string(map, "height", fl_value_new_float(pageHeight));
fl_value_set_string(map, "marginLeft", fl_value_new_float(marginLeft));
fl_value_set_string(map, "marginTop", fl_value_new_float(marginTop));
fl_value_set_string(map, "marginRight", fl_value_new_float(marginRight));
fl_value_set_string(map, "marginBottom", fl_value_new_float(marginBottom));
fl_method_channel_invoke_method(channel, "onLayout", map, nullptr,
on_layout_response_cb, job);
}
void on_completed(print_job* job, bool completed, const char* error) {
g_autoptr(FlValue) map = fl_value_new_map();
fl_value_set_string(map, "job", fl_value_new_int(job->get_id()));
fl_value_set_string(map, "completed", fl_value_new_bool(completed));
if (error != nullptr) {
fl_value_set_string(map, "error", fl_value_new_string(error));
}
fl_method_channel_invoke_method(channel, "onCompleted", map, nullptr, nullptr,
nullptr);
}
\ No newline at end of file
... ...
... ... @@ -38,6 +38,8 @@ flutter:
pluginClass: PrintingPlugin
ios:
pluginClass: PrintingPlugin
linux:
pluginClass: PrintingPlugin
macos:
pluginClass: PrintingPlugin
web:
... ...