Skip to content

Commit 4fa9f86

Browse files
xjl12da-liii
authored andcommitted
!360 [205_1] 初步引入MuPDF插件
* MuPDF: Small changes to adapt API changes * Import original MuPDF plugin written by mgubi * add simple MuPDF xmake package * Import mupdf option in xmake
1 parent ab72407 commit 4fa9f86

File tree

8 files changed

+1899
-1
lines changed

8 files changed

+1899
-1
lines changed

devel/205_1.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# 205_1
2+
## 2025/07/07 初步引入MuPDF插件
3+
## What
4+
1. 在项目xmake配置文件中为mupdf新增编译选项,当选项mupdf启用时,将启用全局宏`USE_MUPDF_RENDERER`,同时编译`src/Plugins/MuPDF`下的插件代码
5+
2. 由于xmake官方尚不支持MuPDF依赖,在项目自带的repo中新增MuPDF包的xmake配置文件
6+
3. 引入原版mgubi编写的MuPDF插件代码,[源地址](https://github.com/texmacs/texmacs/tree/tau/src/Plugins/MuPDF)
7+
4. 修改插件代码中的部分API调用以适配MuPDF、Mogan的版本更新,确保编译通过
8+
9+
## Why
10+
集成MuPDF渲染器
11+
12+
## 如何测试
13+
配置xmake启用mupdf,并编译:
14+
```
15+
xmake f --mupdf=true
16+
xmake build stem
17+
```
18+
目前MuPDF渲染器尚未在核心代码中集成使用,仅能完成编译测试
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
2+
/******************************************************************************
3+
* MODULE : mupdf_picture.cpp
4+
* DESCRIPTION: Picture objects for MuPDF
5+
* COPYRIGHT : (C) 2022 Massimiliano Gubinelli, Joris van der Hoeven
6+
*******************************************************************************
7+
* This software falls under the GNU general public license version 3 or later.
8+
* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9+
* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10+
******************************************************************************/
11+
12+
#include "mupdf_picture.hpp"
13+
14+
#include "effect.hpp"
15+
#include "file.hpp"
16+
#include "image_files.hpp"
17+
#include "tm_url.hpp"
18+
19+
/******************************************************************************
20+
* Abstract mupdf pictures
21+
******************************************************************************/
22+
23+
mupdf_picture_rep::mupdf_picture_rep (fz_pixmap* _pix, int ox2, int oy2)
24+
: pix (_pix), im (NULL), w (fz_pixmap_width (mupdf_context (), pix)),
25+
h (fz_pixmap_height (mupdf_context (), pix)), ox (ox2), oy (oy2) {
26+
fz_keep_pixmap (mupdf_context (), pix);
27+
}
28+
29+
mupdf_picture_rep::~mupdf_picture_rep () {
30+
fz_drop_pixmap (mupdf_context (), pix);
31+
fz_drop_image (mupdf_context (), im);
32+
}
33+
34+
picture_kind
35+
mupdf_picture_rep::get_type () {
36+
return picture_native;
37+
}
38+
void*
39+
mupdf_picture_rep::get_handle () {
40+
return (void*) this;
41+
}
42+
43+
int
44+
mupdf_picture_rep::get_width () {
45+
return w;
46+
}
47+
int
48+
mupdf_picture_rep::get_height () {
49+
return h;
50+
}
51+
int
52+
mupdf_picture_rep::get_origin_x () {
53+
return ox;
54+
}
55+
int
56+
mupdf_picture_rep::get_origin_y () {
57+
return oy;
58+
}
59+
void
60+
mupdf_picture_rep::set_origin (int ox2, int oy2) {
61+
ox= ox2;
62+
oy= oy2;
63+
}
64+
65+
color
66+
mupdf_picture_rep::internal_get_pixel (int x, int y) {
67+
unsigned char* samples= fz_pixmap_samples (mupdf_context (), pix);
68+
return rgbap_to_argb (((color*) samples)[x + w * (h - 1 - y)]);
69+
}
70+
71+
void
72+
mupdf_picture_rep::internal_set_pixel (int x, int y, color c) {
73+
unsigned char* samples= fz_pixmap_samples (mupdf_context (), pix);
74+
((color*) samples)[x + w * (h - 1 - y)]= argb_to_rgbap (c);
75+
}
76+
77+
picture
78+
mupdf_picture (fz_pixmap* _pix, int ox, int oy) {
79+
return (picture) tm_new<mupdf_picture_rep, fz_pixmap*, int, int> (_pix, ox,
80+
oy);
81+
}
82+
83+
picture
84+
as_mupdf_picture (picture pic) {
85+
if (pic->get_type () == picture_native) return pic;
86+
fz_pixmap* pix=
87+
fz_new_pixmap (mupdf_context (), fz_device_rgb (mupdf_context ()),
88+
pic->get_width (), pic->get_height (), NULL, 1);
89+
picture ret= mupdf_picture (pix, pic->get_origin_x (), pic->get_origin_y ());
90+
fz_drop_pixmap (mupdf_context (), pix);
91+
ret->copy_from (pic); // FIXME: is this inefficient???
92+
return ret;
93+
}
94+
95+
#ifdef MUPDF_RENDERER
96+
picture
97+
as_native_picture (picture pict) {
98+
return as_mupdf_picture (pict);
99+
}
100+
101+
picture
102+
native_picture (int w, int h, int ox, int oy) {
103+
fz_pixmap* pix= fz_new_pixmap (
104+
mupdf_context (), fz_device_rgb (mupdf_context ()), w, h, NULL, 1);
105+
fz_clear_pixmap (mupdf_context (), pix);
106+
picture p= mupdf_picture (pix, ox, oy);
107+
fz_drop_pixmap (mupdf_context (), pix);
108+
return p;
109+
}
110+
#endif
111+
112+
/******************************************************************************
113+
* Rendering on images
114+
******************************************************************************/
115+
116+
class mupdf_image_renderer_rep : public mupdf_renderer_rep {
117+
public:
118+
picture pict;
119+
120+
public:
121+
mupdf_image_renderer_rep (picture pict, double zoom);
122+
void* get_data_handle ();
123+
};
124+
125+
mupdf_image_renderer_rep::mupdf_image_renderer_rep (picture p, double zoom)
126+
: mupdf_renderer_rep (), pict (p) {
127+
zoomf = zoom;
128+
shrinkf= (int) tm_round (std_shrinkf / zoomf);
129+
pixel = (SI) tm_round ((std_shrinkf * PIXEL) / zoomf);
130+
thicken= (shrinkf >> 1) * PIXEL;
131+
132+
int pw = p->get_width ();
133+
int ph = p->get_height ();
134+
int pox= p->get_origin_x ();
135+
int poy= p->get_origin_y ();
136+
137+
ox= pox * pixel;
138+
oy= poy * pixel;
139+
/*
140+
cx1= 0;
141+
cy1= 0;
142+
cx2= pw * pixel;
143+
cy2= ph * pixel;
144+
*/
145+
cx1= 0;
146+
cy1= -ph * pixel;
147+
cx2= pw * pixel;
148+
cy2= 0;
149+
150+
mupdf_picture_rep* handle= (mupdf_picture_rep*) pict->get_handle ();
151+
begin (handle->pix);
152+
}
153+
154+
void*
155+
mupdf_image_renderer_rep::get_data_handle () {
156+
return (void*) this;
157+
}
158+
159+
#ifdef MUPDF_RENDERER
160+
renderer
161+
picture_renderer (picture p, double zoomf) {
162+
return (renderer) tm_new<mupdf_image_renderer_rep> (p, zoomf);
163+
}
164+
#endif
165+
166+
/******************************************************************************
167+
* Loading pictures
168+
******************************************************************************/
169+
170+
fz_image*
171+
mupdf_load_image (url u) {
172+
fz_image* im = NULL;
173+
string suf= suffix (u);
174+
if (suf == "svg") {
175+
// FIXME: implement!
176+
#if 0
177+
QSvgRenderer renderer (utf8_to_qstring (concretize (u)));
178+
pm= new QImage (w, h, QImage::Format_ARGB32);
179+
pm->fill (Qt::transparent);
180+
QPainter painter (pm);
181+
renderer.render (&painter);
182+
#endif
183+
}
184+
else if ((suf == "jpg") || (suf == "png")) {
185+
// FIXME: add more supported formats
186+
c_string path (concretize (u));
187+
im= fz_new_image_from_file (mupdf_context (), path);
188+
}
189+
else if (suf == "xpm") {
190+
// try to load higher definition png equivalent if available
191+
url png_equiv= glue (unglue (u, 4), "_x4.png");
192+
if (exists (png_equiv)) {
193+
return mupdf_load_image (png_equiv);
194+
}
195+
png_equiv= glue (unglue (u, 4), "_x2.png");
196+
if (exists (png_equiv)) {
197+
return mupdf_load_image (png_equiv);
198+
}
199+
png_equiv= glue (unglue (u, 4), ".png");
200+
if (exists (png_equiv)) {
201+
return mupdf_load_image (png_equiv);
202+
}
203+
// ok, try to load the xpm finally
204+
picture xp = as_mupdf_picture (load_xpm (u));
205+
fz_pixmap* pix= ((mupdf_picture_rep*) xp->get_handle ())->pix;
206+
im = fz_new_image_from_pixmap (mupdf_context (), pix, NULL);
207+
}
208+
return im;
209+
}
210+
211+
fz_pixmap*
212+
mupdf_load_pixmap (url u, int w, int h, tree eff, SI pixel) {
213+
fz_image* im= mupdf_load_image (u);
214+
215+
if (im == NULL) {
216+
// attempt to convert to png
217+
url temp= url_temp (".png");
218+
image_to_png (u, temp, w, h);
219+
c_string path (as_string (temp));
220+
im= fz_new_image_from_file (mupdf_context (), path);
221+
remove (temp);
222+
}
223+
224+
// Error Handling
225+
if (im == NULL) {
226+
cout << "TeXmacs] warning: cannot render " << concretize (u) << "\n";
227+
return NULL;
228+
}
229+
230+
// Scaling
231+
if (im->w != w || im->h != h) {
232+
// FIXME: implement?
233+
// we opt to draw natively scalables, so here we do not support rescaling
234+
// (*pm)= pm->scaled (w, h, Qt::IgnoreAspectRatio,
235+
// Qt::SmoothTransformation);
236+
cout << "TeXmacs] warning: image rescaling not supported " << concretize (u)
237+
<< "\n";
238+
}
239+
240+
fz_pixmap* pix=
241+
fz_get_pixmap_from_image (mupdf_context (), im, NULL, NULL, NULL, NULL);
242+
fz_drop_image (mupdf_context (), im); // we do not need it anymore
243+
244+
// Build effect
245+
if (eff != "") {
246+
effect e = build_effect (eff);
247+
picture src= mupdf_picture (pix, 0, 0);
248+
array<picture> a;
249+
a << src;
250+
picture pic = e->apply (a, pixel);
251+
picture dest= as_mupdf_picture (pic);
252+
mupdf_picture_rep* rep = (mupdf_picture_rep*) dest->get_handle ();
253+
fz_pixmap* tpix= rep->pix;
254+
fz_drop_pixmap (mupdf_context (), pix);
255+
pix= tpix;
256+
}
257+
return pix;
258+
}
259+
260+
#ifdef MUPDF_RENDERER
261+
picture
262+
load_picture (url u, int w, int h, tree eff, int pixel) {
263+
fz_pixmap* pix= mupdf_load_pixmap (u, w, h, eff, pixel);
264+
if (pix == NULL) return error_picture (w, h);
265+
picture p= mupdf_picture (pix, 0, 0);
266+
fz_drop_pixmap (mupdf_context (), pix);
267+
return p;
268+
}
269+
270+
void
271+
save_picture (url dest, picture p) {
272+
if (suffix (dest) != "png") {
273+
cout << "TeXmacs] warning: cannot save " << concretize (dest)
274+
<< ", format not supported\n";
275+
return;
276+
}
277+
picture q = as_mupdf_picture (p);
278+
mupdf_picture_rep* pict= (mupdf_picture_rep*) q->get_handle ();
279+
if (exists (dest)) remove (dest);
280+
c_string path= concretize (dest);
281+
fz_output* out = fz_new_output_with_path (mupdf_context (), path, 0);
282+
fz_write_pixmap_as_png (mupdf_context (), out, pict->pix);
283+
fz_close_output (mupdf_context (), out);
284+
fz_drop_output (mupdf_context (), out);
285+
}
286+
#endif
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
2+
/******************************************************************************
3+
* MODULE : mupdf_picture.hpp
4+
* DESCRIPTION: Picture objects for MuPDF
5+
* COPYRIGHT : (C) 2022 Massimiliano Gubinelli, Joris van der Hoeven
6+
*******************************************************************************
7+
* This software falls under the GNU general public license version 3 or later.
8+
* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9+
* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10+
******************************************************************************/
11+
12+
#ifndef MUPDF_PICTURE_HPP
13+
#define MUPDF_PICTURE_HPP
14+
15+
#include "mupdf_renderer.hpp"
16+
17+
#include <mupdf/fitz.h>
18+
19+
// in fitz pixmaps are stored in rgba premultiplied format while our color type
20+
// is argb not premultiplied...
21+
// we code for a little endian system
22+
23+
inline color
24+
argb_to_rgbap (color c) {
25+
int r, g, b, a;
26+
get_rgb_color (c, r, g, b, a);
27+
r= ((r * a) / 255) & 0xFF;
28+
g= ((g * a) / 255) & 0xFF;
29+
b= ((b * a) / 255) & 0xFF;
30+
return (a << 24) + (b << 16) + (g << 8) + r;
31+
}
32+
33+
inline color
34+
rgbap_to_argb (color c) {
35+
int r, g, b, a;
36+
a= (c >> 24) & 0xFF;
37+
b= (c >> 16) & 0xFF;
38+
g= (c >> 8) & 0xFF;
39+
r= (c >> 0) & 0xFF;
40+
if (a) {
41+
r= ((r * 255) / a) & 0xFF;
42+
g= ((g * 255) / a) & 0xFF;
43+
b= ((b * 255) / a) & 0xFF;
44+
}
45+
else {
46+
r= g= b= 0;
47+
}
48+
return rgb_color (r, g, b, a);
49+
}
50+
51+
class mupdf_picture_rep : public picture_rep {
52+
public:
53+
fz_pixmap* pix;
54+
fz_image* im;
55+
int w, h;
56+
int ox, oy;
57+
58+
protected:
59+
color internal_get_pixel (int x, int y);
60+
void internal_set_pixel (int x, int y, color c);
61+
62+
public:
63+
mupdf_picture_rep (fz_pixmap* _pix, int ox2, int oy2);
64+
~mupdf_picture_rep ();
65+
66+
picture_kind get_type ();
67+
void* get_handle ();
68+
int get_width ();
69+
int get_height ();
70+
int get_origin_x ();
71+
int get_origin_y ();
72+
void set_origin (int ox2, int oy2);
73+
};
74+
75+
picture mupdf_picture (fz_pixmap* im, int ox, int oy);
76+
picture as_mupdf_picture (picture pic);
77+
78+
fz_image* mupdf_load_image (url u);
79+
fz_pixmap* mupdf_load_pixmap (url u, int w, int h, tree eff, SI pixel);
80+
81+
#endif // defined MUPDF_PICTURE_HPP

0 commit comments

Comments
 (0)