@@ -186,6 +186,7 @@ dictkey_id = PyUnicode_InternFromString("id");
186186dictkey_image = PyUnicode_InternFromString (" image" );
187187dictkey_length = PyUnicode_InternFromString (" length" );
188188dictkey_lines = PyUnicode_InternFromString (" lines" );
189+ dictkey_matrix = PyUnicode_InternFromString (" transform" );
189190dictkey_modDate = PyUnicode_InternFromString (" modDate" );
190191dictkey_name = PyUnicode_InternFromString (" name" );
191192dictkey_number = PyUnicode_InternFromString (" number" );
@@ -2842,44 +2843,30 @@ if not self.is_form_pdf:
28422843 fz_try(gctx) {
28432844 ASSERT_PDF(pdf);
28442845 int xreflen = pdf_xref_len(gctx, pdf);
2845- if (!INRANGE(xref, 1, xreflen-1))
2846+ if (!INRANGE(xref, 1, xreflen-1) && xref != -1 )
28462847 THROWMSG(gctx, "bad xref");
2847- obj = pdf_load_object(gctx, pdf, xref);
2848+ if (xref > 0) {
2849+ obj = pdf_load_object(gctx, pdf, xref);
2850+ } else {
2851+ obj = pdf_trailer(gctx, pdf);
2852+ }
28482853 res = JM_object_to_buffer(gctx, pdf_resolve_indirect(gctx, obj), compressed, ascii);
28492854 text = JM_EscapeStrFromBuffer(gctx, res);
28502855 }
28512856 fz_always(gctx) {
2852- pdf_drop_obj(gctx, obj);
2857+ if (xref > 0) {
2858+ pdf_drop_obj(gctx, obj);
2859+ }
28532860 fz_drop_buffer(gctx, res);
28542861 }
28552862 fz_catch(gctx) return EMPTY_STRING;
28562863 return text;
28572864 }
2865+ %pythoncode %{
2866+ def pdf_trailer(self, compressed: bool=False, ascii:bool=False)->str:
2867+ """Get PDF trailer as a string."""
2868+ return self.xref_object(-1, compressed=compressed, ascii=ascii)%}
28582869
2859- //------------------------------------------------------------------
2860- // Get String of PDF trailer
2861- //------------------------------------------------------------------
2862- FITZEXCEPTION(pdf_trailer, !result)
2863- CLOSECHECK0(pdf_trailer, """Get PDF trailer as a string.""")
2864- PyObject *
2865- pdf_trailer(int compressed=0, int ascii=0)
2866- {
2867- pdf_document *pdf = pdf_specifics(gctx, (fz_document *) $self);
2868- if (!pdf) Py_RETURN_NONE;
2869- PyObject *text = NULL;
2870- fz_buffer *res=NULL;
2871- fz_try(gctx) {
2872- res = JM_object_to_buffer(gctx, pdf_trailer(gctx, pdf), compressed, ascii);
2873- text = JM_EscapeStrFromBuffer(gctx, res);
2874- }
2875- fz_always(gctx) {
2876- fz_drop_buffer(gctx, res);
2877- }
2878- fz_catch(gctx) {
2879- return PyUnicode_FromString("PDF trailer damaged");
2880- }
2881- return text;
2882- }
28832870
28842871 //------------------------------------------------------------------
28852872 // Get compressed stream of an object by xref
@@ -3265,7 +3252,7 @@ if not self.is_form_pdf:
32653252 pdf_obj *item = NULL;
32663253 pdf_obj *obj = NULL;
32673254 Py_ssize_t i;
3268- float f;
3255+ double f;
32693256 pdf_document *pdf = pdf_specifics(gctx, (fz_document *) $self);
32703257 fz_try(gctx) {
32713258 item = pdf_new_indirect(gctx, pdf, xref, 0);
@@ -3873,7 +3860,8 @@ if basestate:
38733860 if not self.is_pdf:
38743861 return ()
38753862 val = self._getPageInfo(pno, 3)
3876- return val
3863+ rc = [(v[0], v[1], v[2], Rect(v[3]), Matrix(v[4])) for v in val]
3864+ return rc
38773865
38783866
38793867 def copy_page(self, pno: int, to: int =-1):
@@ -4156,30 +4144,55 @@ struct Page {
41564144 doc = self.parent
41574145 if doc.is_closed or doc.is_encrypted:
41584146 raise ValueError(" document closed or encrypted" )
4147+
41594148 inf_rect = Rect(1, 1, -1, -1)
4149+ null_mat = Matrix()
4150+ if transform == 1:
4151+ rc = (inf_rect, null_mat)
4152+ else:
4153+ rc = inf_rect
4154+
41604155 if type(name) in (list, tuple):
41614156 if not type(name[-1]) is int:
4162- raise ValueError(" need a full page image list item " )
4157+ raise ValueError(" need item of full page image list" )
41634158 item = name
41644159 else:
41654160 imglist = [i for i in doc.get_page_images(self.number, True) if name == i[-3]]
41664161 if len(imglist) == 1:
41674162 item = imglist[0]
41684163 elif imglist == []:
4169- raise ValueError(" no valid image found " )
4164+ raise ValueError(" bad image name " )
41704165 else:
4171- raise ValueError(" found more than one image of that name." )%}
4166+ raise ValueError(" found multiple images named ' %s' ." % name)
4167+ xref = item[-1]
4168+ if xref != 0:
4169+ xobjs = [x for x in self.get_xobjects() if x[0] == xref and x[2] == 0]
4170+ if xobjs == []:
4171+ raise ValueError(" image in unsupported Form XObject" )
4172+ %}
41724173 %pythonappend get_image_bbox %{
41734174 if not bool(val):
4174- return inf_rect
4175- rc = inf_rect
4175+ return rc
4176+
41764177 for v in val:
4177- if v[0] == item[-3]:
4178- rc = Quad(v[1]).rect
4178+ if v[0] != item[-3]:
4179+ continue
4180+ q = Quad(v[1])
4181+ bbox = q.rect
4182+ if transform == 0:
4183+ rc = bbox
41794184 break
4180- val = rc * self.transformation_matrix%}
4185+
4186+ hm = Matrix(TOOLS._hor_matrix(q.ll, q.lr))
4187+ h = abs(q.ll - q.ul)
4188+ w = abs(q.ur - q.ul)
4189+ m0 = Matrix(1 / w, 0, 0, 1 / h, 0, 0)
4190+ m = ~(hm * m0)
4191+ rc = (bbox, m)
4192+ break
4193+ val = rc%}
41814194 PyObject *
4182- get_image_bbox(PyObject *name)
4195+ get_image_bbox(PyObject *name, int transform=0 )
41834196 {
41844197 pdf_page *pdf_page = pdf_page_from_fz_page(gctx, (fz_page *) $self);
41854198 PyObject *rc =NULL;
@@ -6457,6 +6470,12 @@ def insert_font(self, fontname="helv", fontfile=None, fontbuffer=None,
64576470 return self.parent.get_page_images(self.number, full=full)
64586471
64596472
6473+ def get_xobjects(self):
6474+ " " " List of xobjects defined in the page object." " "
6475+ CheckParent(self)
6476+ return self.parent.get_page_xobjects(self.number)
6477+
6478+
64606479 def read_contents(self):
64616480 " " " All /Contents streams concatenated to one bytes object." " "
64626481 return TOOLS._get_all_contents(self)
@@ -9850,7 +9869,7 @@ struct TextPage {
98509869 } else if (fz_contains_rect(tp_rect, block->bbox) || fz_is_infinite_rect(tp_rect)) {
98519870 fz_image *img = block->u.i.image;
98529871 fz_colorspace *cs = img->colorspace;
9853- text = PyUnicode_FromFormat(" <image: %s, width %d, height %d, bpc %d>" , fz_colorspace_name(gctx, cs), img->w, img->h, img->bpc);
9872+ text = PyUnicode_FromFormat(" <image: %s, width: %d, height: %d, bpc: %d>" , fz_colorspace_name(gctx, cs), img->w, img->h, img->bpc);
98549873 blockrect = fz_union_rect(blockrect, block->bbox);
98559874 }
98569875 if (!fz_is_empty_rect(blockrect)) {
@@ -11167,29 +11186,41 @@ struct Tools
1116711186 fz_point c = JM_point_from_py(C);
1116811187 fz_point p = JM_point_from_py(P);
1116911188 fz_point q = JM_point_from_py(Q);
11170- fz_point s = fz_normalize_vector(fz_make_point( q.x - p.x, q.y - p.y) );
11189+ fz_point s = JM_normalize_vector( q.x - p.x, q.y - p.y);
1117111190 fz_matrix m1 = fz_make_matrix(1, 0, 0, 1, -p.x, -p.y);
1117211191 fz_matrix m2 = fz_make_matrix(s.x, -s.y, s.y, s.x, 0, 0);
1117311192 m1 = fz_concat(m1, m2);
1117411193 c = fz_transform_point(c, m1);
11175- c = fz_normalize_vector(c );
11194+ c = JM_normalize_vector(c.x, c.y );
1117611195 return Py_BuildValue("f", c.y);
1117711196 }
1117811197
11198+ // Return matrix that maps point C to (0,0) and point P to the
11199+ // x-axis such that abs(x) equals abs(P - C).
1117911200 PyObject *
1118011201 _hor_matrix(PyObject *C, PyObject *P)
1118111202 {
11182- // calculate matrix m that maps line CP to the x-axis,
11183- // such that C * m = (0, 0), and target line has same length.
1118411203 fz_point c = JM_point_from_py(C);
1118511204 fz_point p = JM_point_from_py(P);
11186- fz_point s = fz_normalize_vector(fz_make_point(p.x - c.x, p.y - c.y));
11205+
11206+ // compute (cosine, sine) of vector P-C with double precision:
11207+ fz_point s = JM_normalize_vector(p.x - c.x, p.y - c.y);
11208+
1118711209 fz_matrix m1 = fz_make_matrix(1, 0, 0, 1, -c.x, -c.y);
1118811210 fz_matrix m2 = fz_make_matrix(s.x, -s.y, s.y, s.x, 0, 0);
1118911211 return JM_py_from_matrix(fz_concat(m1, m2));
1119011212 }
1119111213
1119211214
11215+ PyObject *
11216+ _point_in_quad(PyObject *P, PyObject *Q)
11217+ {
11218+ fz_point p = JM_point_from_py(P);
11219+ fz_quad q = JM_quad_from_py(Q);
11220+ return JM_BOOL(fz_is_point_inside_quad(p, q));
11221+ }
11222+
11223+
1119311224 FITZEXCEPTION(set_font_width, !result)
1119411225 PyObject *
1119511226 set_font_width(struct Document *doc, int xref, int width)
0 commit comments