This file is indexed.

/usr/lib/python3/dist-packages/pyx/epsfile.py is in python3-pyx 0.14.1-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# -*- encoding: utf-8 -*-
#
#
# Copyright (C) 2002-2011 Jörg Lehmann <joergl@users.sourceforge.net>
# Copyright (C) 2002-2011 André Wobst <wobsta@users.sourceforge.net>
#
# This file is part of PyX (http://pyx.sourceforge.net/).
#
# PyX is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PyX is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyX; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

import logging, os, string, tempfile
from . import baseclasses, bbox, config, unit, trafo, pswriter

logger = logging.getLogger("pyx")

# PostScript-procedure definitions (cf. 5002.EPSF_Spec_v3.0.pdf)
# with important correction in EndEPSF:
#   end operator is missing in the spec!

_BeginEPSF = pswriter.PSdefinition("BeginEPSF", b"""{
  /b4_Inc_state save def
  /dict_count countdictstack def
  /op_count count 1 sub def
  userdict begin
  /showpage { } def
  0 setgray 0 setlinecap
  1 setlinewidth 0 setlinejoin
  10 setmiterlimit [ ] 0 setdash newpath
  /languagelevel where
  {pop languagelevel
  1 ne
    {false setstrokeadjust false setoverprint
    } if
  } if
} bind""")

_EndEPSF = pswriter.PSdefinition("EndEPSF", b"""{
  end
  count op_count sub {pop} repeat
  countdictstack dict_count sub {end} repeat
  b4_Inc_state restore
} bind""")


class linefilereader:
    """a line by line file reader

    This line by line file reader allows for '\n', '\r' and
    '\r\n' as line separation characters. Line separation
    characters are not modified (binary mode). It implements
    a readline, a read and a close method similar to a regular
    file object."""

    # note: '\n\r' is not considered to be a linebreak as its documented
    #       in the DSC spec #5001, while '\n\r' *is* a *single* linebreak
    #       according to the EPSF spec #5002

    def __init__(self, file, typicallinelen=257):
        """Opens the file filename for reading.

        typicallinelen defines the default buffer increase
        to find the next linebreak."""

        # note: The maximal line size in an EPS is 255 plus the
        #       linebreak characters. However, we also handle
        #       lines longer than that.
        self.file = file
        self.buffer = b""
        self.typicallinelen = typicallinelen

    def read(self, count=None, EOFmsg="unexpected end of file"):
        """read bytes from the file

        count is the number of bytes to be read when set. Then count
        is unset, the rest of the file is returned. EOFmsg is used
        to raise a IOError, when the end of the file is reached while
        reading count bytes or when the rest of the file is empty when
        count is unset. When EOFmsg is set to None, less than the
        requested number of bytes might be returned."""
        if count is not None:
            if count > len(self.buffer):
                self.buffer += self.file.read(count - len(self.buffer))
            if EOFmsg is not None and len(self.buffer) < count:
                raise IOError(EOFmsg)
            result = self.buffer[:count]
            self.buffer = self.buffer[count:]
            return result
        else:
            self.buffer += self.file.read()
            if EOFmsg is not None and not len(self.buffer):
                raise IOError(EOFmsg)
            result = self.buffer
            self.buffer = ""
            return result

    def readline(self, EOFmsg="unexpected end of file"):
        """reads a line from the file

        Lines are separated by '\n', '\r' or '\r\n'. The line separation
        strings are included in the return value. The last line might not
        end with an line separation string. Reading beyond the file generates
        an IOError with the EOFmsg message. When EOFmsg is None, an empty
        string is returned when reading beyond the end of the file."""
        EOF = 0
        while True:
            crpos = self.buffer.find(b"\r")
            nlpos = self.buffer.find(b"\n")
            if nlpos == -1 and (crpos == -1 or crpos == len(self.buffer) - 1) and not EOF:
                newbuffer = self.file.read(self.typicallinelen)
                if not len(newbuffer):
                    EOF = 1
                self.buffer += newbuffer
            else:
                eol = len(self.buffer)
                if not eol and EOFmsg is not None:
                    raise IOError(EOFmsg)
                if nlpos != -1:
                    eol = nlpos + 1
                if crpos != -1 and (nlpos == -1 or crpos < nlpos - 1):
                    eol = crpos + 1
                result = self.buffer[:eol]
                self.buffer = self.buffer[eol:]
                return result


def _readbbox(file):
    """returns bounding box of EPS file filename"""

    file = linefilereader(file)

    # check the %! header comment
    if not file.readline().startswith(b"%!"):
        raise IOError("file doesn't start with a '%!' header comment")

    bboxatend = 0
    # parse the header (use the first BoundingBox)
    while True:
        line = file.readline()
        if not line:
            break
        if line.startswith(b"%%BoundingBox:") and not bboxatend:
            values = line.split(b":", 1)[1].split()
            if values == ["(atend)"]:
                bboxatend = 1
            else:
                if len(values) != 4:
                    raise IOError("invalid number of bounding box values")
                return bbox.bbox_pt(*list(map(int, values)))
        elif (line.rstrip() == b"%%EndComments" or
              (len(line) >= 2 and chr(line[0]) != "%" and chr(line[1]) not in string.whitespace)):
            # implicit end of comments section
            break
    if not bboxatend:
        raise IOError("no bounding box information found")

    # parse the body
    nesting = 0 # allow for nested documents
    while True:
        line = file.readline()
        if line.startswith(b"%%BeginData:"):
            values = line.split(":", 1)[1].split()
            if len(values) > 3:
                raise IOError("invalid number of arguments")
            if len(values) == 3:
                if values[2] == b"Lines":
                    for i in range(int(values[0])):
                        file.readline()
                elif values[2] != b"Bytes":
                    raise IOError("invalid bytesorlines-value")
                else:
                    file.read(int(values[0]))
            else:
                file.read(int(values[0]))
            line = file.readline()
            # ignore tailing whitespace/newline for binary data
            if (len(values) < 3 or values[2] != "Lines") and not len(line.strip()):
                line = file.readline()
            if line.rstrip() != b"%%EndData":
                raise IOError("missing EndData")
        elif line.startswith(b"%%BeginBinary:"):
            file.read(int(line.split(":", 1)[1]))
            line = file.readline()
            # ignore tailing whitespace/newline
            if not len(line.strip()):
                line = file.readline()
            if line.rstrip() != b"%%EndBinary":
                raise IOError("missing EndBinary")
        elif line.startswith(b"%%BeginDocument:"):
            nesting += 1
        elif line.rstrip() == b"%%EndDocument":
            if nesting < 1:
                raise IOError("unmatched EndDocument")
            nesting -= 1
        elif not nesting and line.rstrip() == b"%%Trailer":
            break

    usebbox = None
    # parse the trailer (use the last BoundingBox)
    line = True
    while line:
        line = file.readline(EOFmsg=None)
        if line.startswith("%%BoundingBox:"):
            values = line.split(b":", 1)[1].split()
            if len(values) != 4:
                raise IOError("invalid number of bounding box values")
            usebbox = bbox.bbox_pt(*list(map(int, values)))
    if not usebbox:
        raise IOError("missing bounding box information in document trailer")
    return usebbox


class epsfile(baseclasses.canvasitem):

    """class for epsfiles"""

    def __init__(self,
                 x, y, filename,
                 width=None, height=None, scale=None, align="bl",
                 clip=1, translatebbox=1, bbox=None,
                 kpsearch=0):
        """inserts epsfile

        Object for an EPS file named filename at position (x,y). Width, height,
        scale and aligment can be adjusted by the corresponding parameters. If
        clip is set, the result gets clipped to the bbox of the EPS file. If
        translatebbox is not set, the EPS graphics is not translated to the
        corresponding origin. If bbox is not None, it overrides the bounding
        box in the epsfile itself. If kpsearch is set then filename is searched
        using the kpathsea library.
        """

        self.x_pt = unit.topt(x)
        self.y_pt = unit.topt(y)
        self.filename = filename
        self.kpsearch = kpsearch
        if bbox:
            self.mybbox = bbox
        else:
            with self.open() as epsfile:
                self.mybbox = _readbbox(epsfile)

        # determine scaling in x and y direction
        self.scalex = self.scaley = scale

        if width is not None or height is not None:
            if scale is not None:
                raise ValueError("cannot set both width and/or height and scale simultaneously")
            if height is not None:
                self.scaley = unit.topt(height)/(self.mybbox.ury_pt-self.mybbox.lly_pt)
            if width is not None:
                self.scalex = unit.topt(width)/(self.mybbox.urx_pt-self.mybbox.llx_pt)

            if self.scalex is None:
                self.scalex = self.scaley
            if self.scaley is None:
                self.scaley = self.scalex

        # set the actual width and height of the eps file (after a
        # possible scaling)
        self.width_pt  = self.mybbox.urx_pt-self.mybbox.llx_pt
        if self.scalex:
            self.width_pt *= self.scalex

        self.height_pt = self.mybbox.ury_pt-self.mybbox.lly_pt
        if self.scaley:
            self.height_pt *= self.scaley

        # take alignment into account
        self.align       = align
        if self.align[0]=="b":
            pass
        elif self.align[0]=="c":
            self.y_pt -= self.height_pt/2.0
        elif self.align[0]=="t":
            self.y_pt -= self.height_pt
        else:
            raise ValueError("vertical alignment can only be b (bottom), c (center), or t (top)")

        if self.align[1]=="l":
            pass
        elif self.align[1]=="c":
            self.x_pt -= self.width_pt/2.0
        elif self.align[1]=="r":
            self.x_pt -= self.width_pt
        else:
            raise ValueError("horizontal alignment can only be l (left), c (center), or r (right)")

        self.clip = clip
        self.translatebbox = translatebbox

        self.trafo = trafo.translate_pt(self.x_pt, self.y_pt)

        if self.scalex is not None:
            self.trafo = self.trafo * trafo.scale_pt(self.scalex, self.scaley)

        if translatebbox:
            self.trafo = self.trafo * trafo.translate_pt(-self.mybbox.llx_pt, -self.mybbox.lly_pt)

    def open(self):
        if self.kpsearch:
            return config.open(self.filename, [config.format.pict])
        else:
            return open(self.filename, "rb")

    def bbox(self):
        return self.mybbox.transformed(self.trafo)

    def processPS(self, file, writer, context, registry, bbox):
        registry.add(_BeginEPSF)
        registry.add(_EndEPSF)
        bbox += self.bbox()

        file.write("BeginEPSF\n")

        if self.clip:
            llx_pt, lly_pt, urx_pt, ury_pt = self.mybbox.transformed(self.trafo).highrestuple_pt()
            file.write("%g %g %g %g rectclip\n" % (llx_pt, lly_pt, urx_pt-llx_pt, ury_pt-lly_pt))

        self.trafo.processPS(file, writer, context, registry)

        file.write("%%%%BeginDocument: %s\n" % self.filename)

        with self.open() as epsfile:
            file.write_bytes(epsfile.read())

        file.write("%%EndDocument\n")
        file.write("EndEPSF\n")

    def processPDF(self, file, writer, context, registry, bbox):
        logger.warning("EPS file is included as a bitmap created using pipeGS")
        from pyx import bitmap, canvas
        from PIL import Image
        c = canvas.canvas()
        c.insert(self)
        i = Image.open(c.pipeGS(device="pngalpha", resolution=600))
        i.load()
        b = bitmap.bitmap_pt(self.bbox().llx_pt, self.bbox().lly_pt, i)
        # we slightly shift the bitmap to re-center it, as the bitmap might contain some additional border
        # unfortunately we need to construct another bitmap instance for that ...
        b = bitmap.bitmap_pt(self.bbox().llx_pt + 0.5*(self.bbox().width_pt()-b.bbox().width_pt()),
                             self.bbox().lly_pt + 0.5*(self.bbox().height_pt()-b.bbox().height_pt()), i)
        b.processPDF(file, writer, context, registry, bbox)