简体   繁体   English

kivy 剪切文本变形

[英]kivy cut Text out of Shape

as the canvas instructions Stencil and Scissor (which seem to mo me have the same effect) are used to create masks and draw on top of it, im wondering have one could achieve this effect:由于 canvas 指令 Stencil 和 Scissor (在我看来具有相同的效果)用于创建蒙版并在其上绘制,我想知道有没有人可以达到这种效果:

Drawing any shape on top of a background image (so far so easy).在背景图像上绘制任何形状(到目前为止很容易)。 Then cut text out of the shape in order to look through on the background.然后将文本从形状中剪掉,以便在背景上查看。

Is there any solution for that?有什么解决办法吗? Or any kivy/openGL instructions i have missed?或者我错过的任何 kivy/openGL 指令?

Here is something that comes close to what you want.这是接近你想要的东西。 It is a brute force method that makes the text of a kivy.core.text.Label transparent and then uses that texture in a canvas Rectangle:这是一种蛮力方法,使 kivy.core.text.Label 的文本透明,然后在 canvas 矩形中使用该纹理:

from kivy.app import App
from kivy.clock import Clock
from kivy.graphics.context_instructions import Color
from kivy.graphics.texture import Texture
from kivy.graphics.vertex_instructions import Rectangle
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.core.text import Label as CoreLabel

class MyWidget(FloatLayout):
    pass

Builder.load_string('''
<MyWidget>:
    Image:
        source: 'tester.png'
        allow_stretch: True
        keep_ratio: True
''')


class TestApp(App):
    def build(self):
        Clock.schedule_once(self.doit)
        return MyWidget()

    def doit(self, dt):
        # build a Rectangle half the size and centered on the root (MyWidget)
        size = (self.root.width/2, self.root.height/2)
        pos = (self.root.x + (self.root.width - size[0])/2, self.root.y + (self.root.height - size[1])/2)
        with self.root.canvas.after:
            Color(1,1,1,1)
            self.rect = Rectangle(pos=pos, size=size)

        # create a Texture with desired text and desired size
        label = CoreLabel(text='Hello', font_name='Roboto-Bold', font_size=300, valign='center', halign='center',
                          size=self.root.size, color=(1,1,1,1))
        label.refresh()

        # make the actual text transparent, and assign the new Texture to the Rectangle
        self.rect.texture =  self.make_text_transparent(label.texture, (255, 0, 0, 255))

    def make_text_transparent(self, texture, bg_color):
        # bg_color is a 4 tuple of byte values in the range 0-255
        # The normal Label texture is transparent except for the text itself
        # This code changes the texture to make the text transparent, and everything else
        # gets set to bg_color
        pixels = list(texture.pixels)
        for index in range(3, len(pixels)-4, 4):
            if pixels[index] == 0:
                # change transparent pixels to the bg_color
                pixels[index-3:index+1] = bg_color
            else:
                # make the text itself transparent
                pixels[index] = 0

        # create a new texture, blit the new pixels, and return the new texture
        new_texture = Texture.create(size=texture.size, colorfmt='rgba')
        new_texture.blit_buffer(bytes(pixels), colorfmt='rgba', bufferfmt='ubyte')
        new_texture.flip_vertical()
        return new_texture

TestApp().run()

You could generalize this by using another Texture, instead of bg_color and setting the transparent Label pixels to the corresponding pixel from the supplied Texture.您可以通过使用另一个纹理而不是bg_color并将透明Label像素设置为提供的纹理中的相应像素来概括这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM