Exemple #1
0
def _init_state():
    global surface
    surface = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, None)
    _state["ctx"] = cairo.Context(surface)
    _state["color"] = (0, 0, 0, 1)
    _state["depth"] = 0
    _state["cnt_elements"] = 0
Exemple #2
0
    def path(self):
        if not self._pang_ctx:
            self._pre_render()

        # here we create a new cairo.Context in order to hold the pathdata
        tempCairoContext = cairo.Context(cairo.RecordingSurface(cairo.CONTENT_ALPHA, None))
        if GI:
            tempCairoContext = _UNSAFE_cairocffi_context_to_pycairo(tempCairoContext)
        tempCairoContext.move_to(self.x, self.y - self.baseline)
        # in here we create a pangoCairoContext in order to display layout on it

        # supposedly showlayout should work, but it fills the path instead,
        # therefore we use layout_path instead to render the layout to pangoCairoContext
        # tempCairoContext.show_layout(self.layout)
        PangoCairo.layout_path(tempCairoContext, self.layout)
        # here we extract the path from the temporal cairo.Context we used to draw on the previous step
        pathdata = tempCairoContext.copy_path()

        # creates a BezierPath instance for storing new shoebot path
        p = BezierPath(self._bot)

        # parsing of cairo path to build a shoebot path
        for item in pathdata:
            cmd = item[0]
            args = item[1]
            if cmd == PATH_MOVE_TO:
                p.moveto(*args)
            elif cmd == PATH_LINE_TO:
                p.lineto(*args)
            elif cmd == PATH_CURVE_TO:
                p.curveto(*args)
            elif cmd == PATH_CLOSE_PATH:
                p.closepath()
        # cairo function for freeing path memory
        return p
Exemple #3
0
    def _pre_render(self):
        # we use a new CairoContext to pre render the text
        rs = cairo.RecordingSurface(cairo.CONTENT_ALPHA, None)
        cr = cairo.Context(rs)

        if GI:
            cr = _UNSAFE_cairocffi_context_to_pycairo(cr)
        self._pang_ctx = PangoCairo.create_context(cr)
        self.layout = PangoCairo.create_layout(cr)
        # layout line spacing
        # TODO: the behaviour is not the same as nodebox yet
        # self.layout.set_spacing(int(((self._lineheight-1)*self._fontsize)*Pango.SCALE)) #pango requires an int casting
        # we pass pango font description and the text to the pango layout
        self.layout.set_font_description(self._fontface)
        self.layout.set_text(self.text, -1)
        # check if max text width is set and pass it to pango layout
        # text will wrap, meanwhile it checks if and indent has to be applied
        # indent is subordinated to width because it makes no sense on a single-line text block
        if self.width:
            self.layout.set_width(int(self.width) * Pango.SCALE)
            if self._indent:
                self.layout.set_indent(self._indent * Pango.SCALE)
        # set text alignment
        if self._align == "right":
            self.layout.set_alignment(Pango.Alignment.RIGHT)
        elif self._align == "center":
            self.layout.set_alignment(Pango.Alignment.CENTER)
        elif self._align == "justify":
            self.layout.set_alignment(Pango.Alignment.LEFT)
            self.layout.set_justify(True)
        else:
            self.layout.set_alignment(Pango.Alignment.LEFT)
Exemple #4
0
def silt_pattern():
    p_surface = \
        cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (0, 0, 32, 8))
    ctx = cairo.Context(p_surface)
    ctx.set_line_width(.5)
    ctx.set_line_cap(cairo.LINE_CAP_ROUND)
    r = 0.5
    sc = 2
    yoffs = 1
    ctx.set_source_rgb(0, 0, 0)

    def dot(x, y):
        ctx.arc(x * sc, y * sc + yoffs, r, 0, 2 * pi)
        ctx.fill()

    def hz_line(x0, x1, y):
        ctx.move_to(x0 * sc, y * sc + yoffs)
        ctx.line_to(x1 * sc, y * sc + yoffs)
        ctx.stroke()

    hz_line(0.2, 7.8, 1)
    hz_line(8.2, 15.8, 3)
    for x in 10, 12, 14:
        dot(x, 1)
    for x in 2, 4, 6:
        dot(x, 3)
    pattern = cairo.SurfacePattern(p_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)
    return pattern
Exemple #5
0
 def _reset_surface(self):
     """This creates a fresh surface and cairo context."""
     self.surface = cairocffi.RecordingSurface(
         cairocffi.CONTENT_COLOR_ALPHA,
         None,
     )
     self.ctx = self.new_ctx()
Exemple #6
0
 def _reset_surface(self):
     if self.surface is not None:
         self.surface.finish()
     self.surface = cairocffi.RecordingSurface(
         cairocffi.CONTENT_COLOR_ALPHA,
         None,
     )
     self.ctx = self.new_ctx()
Exemple #7
0
    def create_rcontext(self, size, frame):
        '''
        Creates a recording surface for the bot to draw on
        '''
        width, height = size
        if self.get_window() and not self.size:
            self.set_size_request(*size)
            self.size = size
        meta_surface = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA,
                                              (0, 0, width, height))

        ctx = cairo.Context(meta_surface)
        return ctx
Exemple #8
0
def burrow_pattern():
    p_surface = \
        cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (0, 0, 36, 36))
    ctx = cairo.Context(p_surface)
    random.seed(17)
    ctx.set_source_rgb(0, 0, 0)
    for x in range(0, 4):
        for y in range(0, 2):
            burrow(ctx, 4.5 + x * 24 + random.random() * 8,
                   9 + y * 36 + random.random() * 8 + x * 8, 2)
    pattern = cairo.SurfacePattern(p_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)
    return pattern
Exemple #9
0
    def contains(self, x, y):
        '''
        Return cached bounds of this Grob.
        If bounds are not cached, render to a meta surface, and
        keep the meta surface and bounds cached.
        '''
        if self._bounds:
            return self._bounds

        record_surface = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (-1, -1, 1, 1))
        dummy_ctx = cairo.Context(record_surface)
        self._traverse(dummy_ctx)

        in_fill = dummy_ctx.in_fill(x, y)
        return in_fill
Exemple #10
0
    def _get_bounds(self):
        '''
        Return cached bounds of this Grob.
        If bounds are not cached, render to a meta surface, and
        keep the meta surface and bounds cached.
        '''
        if self._bounds:
            return self._bounds

        record_surface = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (-1, -1, 1, 1))
        dummy_ctx = cairo.Context(record_surface)
        self._traverse(dummy_ctx)

        self._bounds = dummy_ctx.path_extents()
        return self._bounds
Exemple #11
0
def sand_pattern():
    p_surface = \
        cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (0, 0, 36, 36))
    p_ctx = cairo.Context(p_surface)
    r = 0.5
    wiggle = 3
    sc = 3.6
    offs = 1.8
    random.seed(11)
    p_ctx.set_source_rgb(0, 0, 0)
    for x in range(0, 10):
        for y in range(0, 10):
            p_ctx.arc(offs + x * sc + random.random() * wiggle - wiggle / 2,
                      offs + y * sc + random.random() * wiggle - wiggle / 2,
                      r, 0, 2 * pi)
            p_ctx.fill()
    # for x in range(0,2):
    #     for y in range(0,2):
    #         burrow(p_ctx, 4.5+x*18+random.random()*8.-8./2.,
    #                   9+y*18+random.random()*8.-8./2., 2)
    pattern = cairo.SurfacePattern(p_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)
    return pattern
Exemple #12
0
    def textWithoutNewlinesToLines(self,
                                   text: str,
                                   equal_widths=True,
                                   hyphenate=True) -> List[Line]:
        if text.strip() == "":
            return [Line(0, self.params.line_height)]

        ans = []
        layouts = [(word, self.createLayout(word)) for word in text.split(" ")]

        while layouts:
            surf = cairo.RecordingSurface(cairo.CONTENT_ALPHA, None)
            context = cairo.Context(surf)
            context.set_source_rgb(0, 0, 0)

            i = 0
            il = []
            wsum = 0
            for word, layout in layouts:
                _, _, w, h = getLayoutExtent(layout)
                w, h = self._fixXY(w, h)
                if wsum + len(
                        il
                ) * self.params.min_word_gap + w > self.params.line_width:
                    if hyphenate and voikko and "-" not in word:
                        syllables = re.split(r"-", voikko.hyphenate(word))
                        for j in range(len(syllables), 0, -1):
                            text = "".join(syllables[0:j])
                            if len(stripMarkup(text)) <= 1:
                                break

                            new_l = self.createLayout(text + "-")
                            _, _, new_w, new_h = getLayoutExtent(new_l)
                            new_w, new_h = self._fixXY(new_w, new_h)
                            if wsum + len(
                                    il
                            ) * self.params.min_word_gap + new_w <= self.params.line_width:
                                il.append(new_l)
                                wsum += new_w
                                layout.set_markup(
                                    fixMarkup("".join(syllables[j:])))
                                break

                    word_gap = (self.params.line_width - wsum) / (
                        len(il) -
                        1) if len(il) > 1 else self.params.min_word_gap
                    break

                il.append(layout)
                wsum += w
                i += 1

            else:
                word_gap = self.params.min_word_gap

            if i == 0:
                _, _, w, h = getLayoutExtent(layouts[0][1])
                w, h = self._fixXY(w, h)
                il.append(layouts[0][1])
                wsum = w
                i += 1

            x = 0

            if self.params.text_align == "center":
                word_gap = self.params.min_word_gap
                x = (self.params.line_width - wsum -
                     len(il) * self.params.min_word_gap) / 2

            width = -word_gap
            height = self.params.line_height
            for l in il:
                context.translate(*self._fixXY(x, 0))
                #pangocairo.update_context(context, l.get_context())
                pangocairo.show_layout(context, l)
                context.translate(*self._fixXY(-x, 0))
                _, _, w, h = getLayoutExtent(l)
                w, h = self._fixXY(w, h)
                x += word_gap + w
                width += word_gap + w
                if h > height:
                    height = h

            if self.params.text_align == "center":
                width = self.params.line_width

            del layouts[:i]

            if height != self.params.line_height:
                print(f"Liian pitkä rivi: {height} {repr(text)}")

            ans.append(TextLine(surf, width, height,
                                indent=self.params.indent))

        # Aseta rivien leveystiedot yhdenmukaiseksi sarakealgoritmia varten
        if equal_widths:
            width = max(line.width for line in ans)
            for line in ans:
                line.width = width

        return ans
Exemple #13
0
 def _get_context(self):
     self._ctx = self._ctx or cairo.Context(cairo.RecordingSurface(cairo.CONTENT_ALPHA, None))
     return self._ctx
 def _create_surface(self, width, height):
     cairo_surface = cairocffi.RecordingSurface(
         cairocffi.CONTENT_COLOR_ALPHA, (0, 0, width, height))
     return cairo_surface, width, height
Exemple #15
0
import cairocffi as cairo

recording = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, None)
rcontext = cairo.Context(recording)
with rcontext:
    rcontext.set_source_rgba(0, 0, 0, 0)
    rcontext.paint()

rcontext.move_to(0, 14)
rcontext.set_font_size(14)
text = "*****@*****.**"
rcontext.show_text(text)

xoffset, yoffset, xsize, ysize = recording.ink_extents()
print xoffset, yoffset, xsize, ysize

surface = cairo.SVGSurface("content/extra/email_address.svg",
                           xsize + xoffset * 2, ysize + yoffset * 2)
context = cairo.Context(surface)
context.set_source_surface(recording, 0, 0)
context.paint()
Exemple #16
0
    def __init__(self, bot, path=None, x=0, y=0, width=None, height=None, alpha=1.0, data=None, pathmode=CORNER, **kwargs):
        Grob.__init__(self, bot)
        ColorMixin.__init__(self, **kwargs)

        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.alpha = alpha
        self.path = path
        self.data = data
        self._pathmode = pathmode
        sh = sw = None  # Surface Height and Width

        if isinstance(self.data, cairo.ImageSurface):
            sw = self.data.get_width()
            sh = self.data.get_height()
            self._imagesurface = self.data
        else:
            # checks if image data is passed in command call, in this case it wraps
            # the data in a StringIO oject in order to use it as a file
            # the data itself must contain an entire image, not just pixel data
            # it can be useful for example to retrieve images from the web without
            # writing temp files (e.g. using nodebox's web library, see example 1 of the library)
            # if no data is passed the path is used to open a local file
            if self.data is None:
                surfaceref = self._surface_cache.get(path)
                if surfaceref:
                    imagesurface = surfaceref.surface
                    sw = imagesurface.get_width()
                    sh = imagesurface.get_height()
                elif os.path.splitext(path)[1].lower() == '.svg' and rsvg is not None:
                    handle = rsvg.Handle(path)
                    sw, sh = handle.get_dimension_data()[:2]
                    imagesurface = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, 0, 0, sw, sh)
                    ctx = cairo.Context(imagesurface)
                    handle.render_cairo(ctx)
                elif os.path.splitext(path)[1].lower() == '.png':
                    imagesurface = cairo.ImageSurface.create_from_png(path)
                    sw = imagesurface.get_width()
                    sh = imagesurface.get_height()
                else:
                    img = PILImage.open(path)

                    if img.mode != 'RGBA':
                        img = img.convert("RGBA")

                    sw, sh = img.size
                    # Would be nice to not have to do some of these conversions :-\
                    bgra_data = img.tobytes('raw', 'BGRA', 0, 1)
                    bgra_array = array.array('B', bgra_data)
                    imagesurface = cairo.ImageSurface.create_for_data(bgra_array, cairo.FORMAT_ARGB32, sw, sh, sw * 4)

                self._surface_cache[path] = SurfaceRef(imagesurface)
            else:
                img = PILImage.open(StringIO(self.data))

                if img.mode != 'RGBA':
                    img = img.convert("RGBA")

                sw, sh = img.size
                # Would be nice to not have to do some of these conversions :-\
                bgra_data = img.tobytes('raw', 'BGRA', 0, 1)
                bgra_array = array.array('B', bgra_data)
                imagesurface = cairo.ImageSurface.create_for_data(bgra_array, cairo.FORMAT_ARGB32, sw, sh, sw * 4)

            if width is not None or height is not None:
                if width:
                    wscale = float(width) / sw
                else:
                    wscale = 1.0
                if height:
                    hscale = float(height) / sh
                else:
                    if width:
                        hscale = wscale
                    else:
                        hscale = 1.0
                self._transform.scale(wscale, hscale)

            self.width = width or sw
            self.height = height or sh
            self._imagesurface = imagesurface

        self._deferred_render()