This file is indexed.

/usr/share/pyshared/pyglet/font/base.py is in python-pyglet 1.1.4.dfsg-2.

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
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# ----------------------------------------------------------------------------
# pyglet
# Copyright (c) 2006-2008 Alex Holkner
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#  * Neither the name of pyglet nor the names of its
#    contributors may be used to endorse or promote products
#    derived from this software without specific prior written
#    permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ----------------------------------------------------------------------------

'''Abstract classes used by pyglet.font implementations.

These classes should not be constructed directly.  Instead, use the functions
in `pyglet.font` to obtain platform-specific instances.  You can use these
classes as a documented interface to the concrete classes.
'''

__docformat__ = 'restructuredtext'
__version__ = '$Id: base.py 2541 2009-12-31 04:31:11Z benjamin.coder.smith@gmail.com $'

import unicodedata

from pyglet.gl import *
from pyglet import image

_other_grapheme_extend = \
    map(unichr, [0x09be, 0x09d7, 0x0be3, 0x0b57, 0x0bbe, 0x0bd7, 0x0cc2,
                 0x0cd5, 0x0cd6, 0x0d3e, 0x0d57, 0x0dcf, 0x0ddf, 0x200c,
                 0x200d, 0xff9e, 0xff9f]) # skip codepoints above U+10000
_logical_order_exception = \
    map(unichr, range(0xe40, 0xe45) + range(0xec0, 0xec4))

_grapheme_extend = lambda c, cc: \
    cc in ('Me', 'Mn') or c in _other_grapheme_extend

_CR = u'\u000d'
_LF = u'\u000a'
_control = lambda c, cc: cc in ('ZI', 'Zp', 'Cc', 'Cf') and not \
    c in map(unichr, [0x000d, 0x000a, 0x200c, 0x200d])
_extend = lambda c, cc: _grapheme_extend(c, cc) or \
    c in map(unichr, [0xe30, 0xe32, 0xe33, 0xe45, 0xeb0, 0xeb2, 0xeb3])
_prepend = lambda c, cc: c in _logical_order_exception
_spacing_mark = lambda c, cc: cc == 'Mc' and c not in _other_grapheme_extend

def _grapheme_break(left, right):
    # GB1
    if left is None:
        return True

    # GB2 not required, see end of get_grapheme_clusters

    # GB3
    if left == _CR and right == _LF:
        return False

    left_cc = unicodedata.category(left)

    # GB4
    if _control(left, left_cc):
        return True

    right_cc = unicodedata.category(right)

    # GB5
    if _control(right, right_cc):
        return True

    # GB6, GB7, GB8 not implemented

    # GB9
    if _extend(right, right_cc):
        return False

    # GB9a
    if _spacing_mark(right, right_cc):
        return False

    # GB9b
    if _prepend(left, left_cc):
        return False

    # GB10
    return True

def get_grapheme_clusters(text):
    '''Implements Table 2 of UAX #29: Grapheme Cluster Boundaries.

    Does not currently implement Hangul syllable rules.

    :Parameters:
        `text` : unicode
            String to cluster.

    :since: pyglet 1.1.2

    :rtype: List of `unicode`
    :return: List of Unicode grapheme clusters
    '''
    clusters = []
    cluster = ''
    left = None
    for right in text:
        if cluster and _grapheme_break(left, right):
            clusters.append(cluster)
            cluster = ''
        elif cluster:
            # Add a zero-width space to keep len(clusters) == len(text)
            clusters.append(u'\u200b')
        cluster += right
        left = right

    # GB2
    if cluster:
        clusters.append(cluster)
    return clusters

class Glyph(image.TextureRegion):
    '''A single glyph located within a larger texture.

    Glyphs are drawn most efficiently using the higher level APIs, for example
    `GlyphString`.

    :Ivariables:
        `advance` : int
            The horizontal advance of this glyph, in pixels.
        `vertices` : (int, int, int, int)
            The vertices of this glyph, with (0,0) originating at the
            left-side bearing at the baseline.

    '''

    advance = 0
    vertices = (0, 0, 0, 0)

    def set_bearings(self, baseline, left_side_bearing, advance):
        '''Set metrics for this glyph.

        :Parameters:
            `baseline` : int
                Distance from the bottom of the glyph to its baseline;
                typically negative.
            `left_side_bearing` : int
                Distance to add to the left edge of the glyph.
            `advance` : int
                Distance to move the horizontal advance to the next glyph.

        '''
        self.advance = advance
        self.vertices = (
            left_side_bearing,
            -baseline,
            left_side_bearing + self.width,
            -baseline + self.height)

    def draw(self):
        '''Debug method.

        Use the higher level APIs for performance and kerning.
        '''
        glBindTexture(GL_TEXTURE_2D, self.owner.id)
        glBegin(GL_QUADS)
        self.draw_quad_vertices()
        glEnd()

    def draw_quad_vertices(self):
        '''Debug method.

        Use the higher level APIs for performance and kerning.
        '''
        glTexCoord3f(*self.tex_coords[:3])
        glVertex2f(self.vertices[0], self.vertices[1])
        glTexCoord3f(*self.tex_coords[3:6])
        glVertex2f(self.vertices[2], self.vertices[1])
        glTexCoord3f(*self.tex_coords[6:9])
        glVertex2f(self.vertices[2], self.vertices[3])
        glTexCoord3f(*self.tex_coords[9:12])
        glVertex2f(self.vertices[0], self.vertices[3])

    def get_kerning_pair(self, right_glyph):
        '''Not implemented.
        '''
        return 0

class GlyphTextureAtlas(image.Texture):
    '''A texture within which glyphs can be drawn.
    '''
    region_class = Glyph
    x = 0
    y = 0
    line_height = 0

    def apply_blend_state(self):
        '''Set the OpenGL blend state for the glyphs in this texture.
        '''
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_BLEND)

    def fit(self, image):
        '''Place `image` within this texture.

        :Parameters:
            `image` : `pyglet.image.AbstractImage`
                Image to place within the texture.

        :rtype: `Glyph`
        :return: The glyph representing the image from this texture, or None
            if the image doesn't fit.
        '''
        if self.x + image.width > self.width:
            self.x = 0
            self.y += self.line_height
            self.line_height = 0
        if self.y + image.height > self.height:
            return None

        self.line_height = max(self.line_height, image.height)
        region = self.get_region(
            self.x, self.y, image.width, image.height)
        if image.width > 0:
            region.blit_into(image, 0, 0, 0)
            self.x += image.width + 1
        return region

class GlyphRenderer(object):
    '''Abstract class for creating glyph images.
    '''
    def __init__(self, font):
        pass

    def render(self, text):
        raise NotImplementedError('Subclass must override')

class FontException(Exception):
    '''Generic exception related to errors from the font module.  Typically
    these relate to invalid font data.'''
    pass

class Font(object):
    '''Abstract font class able to produce glyphs.

    To construct a font, use `pyglet.font.load`, which will instantiate the
    platform-specific font class.

    Internally, this class is used by the platform classes to manage the set
    of textures into which glyphs are written.

    :Ivariables:
        `ascent` : int
            Maximum ascent above the baseline, in pixels.
        `descent` : int
            Maximum descent below the baseline, in pixels. Usually negative.
    '''
    texture_width = 256
    texture_height = 256
    texture_internalformat = GL_ALPHA

    # These should also be set by subclass when known
    ascent = 0
    descent = 0

    glyph_renderer_class = GlyphRenderer
    texture_class = GlyphTextureAtlas

    def __init__(self):
        self.textures = []
        self.glyphs = {}

    @classmethod
    def add_font_data(cls, data):
        '''Add font data to the font loader.

        This is a class method and affects all fonts loaded.  Data must be
        some byte string of data, for example, the contents of a TrueType font
        file.  Subclasses can override this method to add the font data into
        the font registry.

        There is no way to instantiate a font given the data directly, you
        must use `pyglet.font.load` specifying the font name.
        '''
        pass

    @classmethod
    def have_font(cls, name):
        '''Determine if a font with the given name is installed.

        :Parameters:
            `name` : str
                Name of a font to search for

        :rtype: bool
        '''
        return True

    def create_glyph(self, image):
        '''Create a glyph using the given image.

        This is used internally by `Font` subclasses to add glyph data
        to the font.  Glyphs are packed within large textures maintained by
        `Font`.  This method inserts the image into a font texture and returns
        a glyph reference; it is up to the subclass to add metadata to the
        glyph.

        Applications should not use this method directly.

        :Parameters:
            `image` : `pyglet.image.AbstractImage`
                The image to write to the font texture.

        :rtype: `Glyph`
        '''
        glyph = None
        for texture in self.textures:
            glyph = texture.fit(image)
            if glyph:
                break
        if not glyph:
            if image.width > self.texture_width or \
               image.height > self.texture_height:
                texture = self.texture_class.create_for_size(GL_TEXTURE_2D,
                    image.width * 2, image.height * 2,
                    self.texture_internalformat)
                self.texture_width = texture.width
                self.texture_height = texture.height
            else:
                texture = self.texture_class.create_for_size(GL_TEXTURE_2D,
                    self.texture_width, self.texture_height,
                    self.texture_internalformat)
            self.textures.insert(0, texture)
            glyph = texture.fit(image)
        return glyph

    def get_glyphs(self, text):
        '''Create and return a list of Glyphs for `text`.

        If any characters do not have a known glyph representation in this
        font, a substitution will be made.

        :Parameters:
            `text` : str or unicode
                Text to render.

        :rtype: list of `Glyph`
        '''
        glyph_renderer = None
        glyphs = []         # glyphs that are committed.
        for c in get_grapheme_clusters(unicode(text)):
            # Get the glyph for 'c'.  Hide tabs (Windows and Linux render
            # boxes)
            if c == '\t':
                c = ' '
            if c not in self.glyphs:
                if not glyph_renderer:
                    glyph_renderer = self.glyph_renderer_class(self)
                self.glyphs[c] = glyph_renderer.render(c)
            glyphs.append(self.glyphs[c])
        return glyphs


    def get_glyphs_for_width(self, text, width):
        '''Return a list of glyphs for `text` that fit within the given width.

        If the entire text is larger than 'width', as much as possible will be
        used while breaking after a space or zero-width space character.  If a
        newline is encountered in text, only text up to that newline will be
        used.  If no break opportunities (newlines or spaces) occur within
        `width`, the text up to the first break opportunity will be used (this
        will exceed `width`).  If there are no break opportunities, the entire
        text will be used.

        You can assume that each character of the text is represented by
        exactly one glyph; so the amount of text "used up" can be determined
        by examining the length of the returned glyph list.

        :Parameters:
            `text` : str or unicode
                Text to render.
            `width` : int
                Maximum width of returned glyphs.

        :rtype: list of `Glyph`

        :see: `GlyphString`
        '''
        glyph_renderer = None
        glyph_buffer = []   # next glyphs to be added, as soon as a BP is found
        glyphs = []         # glyphs that are committed.
        for c in text:
            if c == '\n':
                glyphs += glyph_buffer
                break

            # Get the glyph for 'c'
            if c not in self.glyphs:
                if not glyph_renderer:
                    glyph_renderer = self.glyph_renderer_class(self)
                self.glyphs[c] = glyph_renderer.render(c)
            glyph = self.glyphs[c]

            # Add to holding buffer and measure
            glyph_buffer.append(glyph)
            width -= glyph.advance

            # If over width and have some committed glyphs, finish.
            if width <= 0 and len(glyphs) > 0:
                break

            # If a valid breakpoint, commit holding buffer
            if c in u'\u0020\u200b':
                glyphs += glyph_buffer
                glyph_buffer = []

        # If nothing was committed, commit everything (no breakpoints found).
        if len(glyphs) == 0:
            glyphs = glyph_buffer

        return glyphs