예제 #1
0
 def curve_func(step):
     subcurve_idx = step // nr_sides
     side_idx = step % nr_sides
     # distance from centre of polygons to centre of one side of outermost polygon =
     #    radius * math.sin(corner_angle / 2)
     # therefore, distance from centre of polygons to corner of next-inner polygon =
     #    radius * step_scale_factor
     # such that
     #     step_scale_factor = math.sin(corner_angle / 2) / math.cos(math.pi / nr_sides - abs(step_rotate))
     # where
     #     step_rotate = math.pi / nr_sides * poly_shrink
     step_rotate = math.pi / nr_sides * poly_shrink
     corner_angle = (0.5 - 1 / nr_sides) * qah.circle
     step_scale_factor = math.sin(
         corner_angle / 2) / math.cos(math.pi / nr_sides - abs(step_rotate))
     scale = step_scale_factor**subcurve_idx
     rotate = \
         (
             phase
         +
             step_rotate * subcurve_idx
         +
             qah.circle / nr_sides * side_idx
         )
     return \
         qah.Vector(radius * scale, 0).rotate(rotate)
예제 #2
0
    def draw(self, cr, pos):
        self.strip()

        for drawColorLayers in (False, True):
            p = qh.Vector(pos.x, pos.y)
            for box in self.boxes:
                p.x = box.draw(cr, p, drawColorLayers)
예제 #3
0
 def curve_func(n):
     subcurve = n // mod // k
     step = n * delta % mod
     phi = qah.circle * (step + subcurve) / mod
     theta = qah.circle * ((step + subcurve) * freq / mod + phase)
     r = offset + math.sin(theta) * amplitude
     return \
         qah.Vector(r * math.cos(phi), r * math.sin(phi))
    def get_page_number_pos(self, page, width):
        pos = qh.Vector(0, self.page_number_ypos)

        # Center the number relative to the text box.
        line = self.lines_per_page - 1
        text_width = self.get_text_width(line)
        pos.x = self.get_text_start_pos(page, line)
        pos.x -= text_width / 2

        # Center the box around the position
        pos.x -= width / 2

        return pos
    def draw(self, cr):
        logger.info("Page %d…", self.number)

        shaper = self.doc.shaper
        self.cr = cr

        if not self.lines:
            logger.debug("Leaving empty page blank")
            cr.show_page()
            return

        self.strip()

        lines = self.lines
        pos = qh.Vector(0, self.doc.top_margin)
        for i, line in enumerate(lines):
            pos.x = self.doc.get_text_start_pos(self, i)
            text_width = self.doc.get_text_width(i)
            line.draw(cr, pos, text_width)
            if line.get_quarter() or line.get_prostration():
                self._show_quarter(line, line.get_quarter(),
                                   line.get_prostration(), pos.y)
            pos.y += line.height

        # Show page number.
        box = shaper.shape_word(format_number(self.number))
        pos = self.doc.get_page_number_pos(self, box.width)
        box.draw(cr, pos)

        # Draw page decorations.
        if self.doc.page_decorations:
            o = 8
            x = self.doc.get_text_start_pos(self, 0) + o
            y = self.doc.top_margin - self.doc.leading / 2 - o
            w = self.doc.get_text_width(0) + o * 2
            h = self.doc.leading * self.doc.lines_per_page + o

            cr.save()
            rect = qh.Rect(x - w, y, w, h)
            cr.rectangle(rect)
            cr.set_line_width(1)
            cr.stroke()
            cr.rectangle(rect.inset((-5, -5)))
            cr.set_line_width(3)
            cr.stroke()
            cr.restore()

        cr.show_page()
    def draw(self, cr, pos, width):
        offset = self.doc.leading / 2
        height = self.height - offset

        linepos = qh.Vector(pos.x, pos.y)
        for line in self.boxes:
            line.draw(cr, linepos, width)
            linepos.x = pos.x
            linepos.y += line.height - offset / 1.2

        cr.save()
        cr.set_line_width(0.5)
        cr.move_to((pos.x, pos.y - offset))
        cr.rectangle(qh.Rect(pos.x - width, pos.y - offset, width, height))
        cr.stroke()
        cr.restore()
예제 #7
0
    def draw(self, cr):
        logger.info("Page %d…", self.number)

        shaper = self.doc.shaper
        self.cr = cr

        if not self.lines:
            logger.debug("Leaving empty page blank")
            cr.show_page()
            return

        lines = self.lines
        pos = qh.Vector(self.doc.text_start_pos, self.doc.top_margin)
        for i, line in enumerate(lines):
            line.draw(cr, pos)
            pos.y += line.height

        cr.show_page()
예제 #8
0
    def shape_verse(self, verse, mark=None):
        """
        Shapes a single verse and returns the corresponding nodes.
        """

        buf = self.shape(verse, hb.HARFBUZZ.DIRECTION_RTL)

        nodes = []
        infos = buf.glyph_infos
        positions = buf.glyph_positions
        flip = qh.Vector(1, -1)
        i = len(infos) - 1
        while i >= 0:
            # Find all indices with same cluster
            j = i
            while j >= 0 and infos[i].cluster == infos[j].cluster:
                j -= 1

            # Collect all glyphs in this cluster, iterating backwards to get
            # glyphs in the visual order.
            pos = qh.Vector(0, 0)
            glyphs = []
            for k in reversed(range(i, j, -1)):
                glyphs.append(
                    qh.Glyph(infos[k].codepoint,
                             pos + flip * positions[k].offset))
                pos += flip * positions[k].advance

            # The chars in this cluster
            chars = verse[infos[i].cluster:infos[j].cluster]

            # We skip space since the font kerns with it and we will turn these
            # kerns into glue below.
            if chars != " ":
                # Find the last non-combining mark char in the string, to check
                # for joining behaviour.
                for ch in chars:
                    if not unicodedata.combining(ch):
                        base = ch

                adv = self.font.get_glyph_h_advance(glyphs[-1].index)
                minadv = self.minfont.get_glyph_h_advance(glyphs[-1].index)
                maxadv = self.maxfont.get_glyph_h_advance(glyphs[-1].index)

                shrink = adv - minadv
                stretch = maxadv - adv

                if base in RIGH_JOINING or self.next_is_nonjoining(
                        verse, infos, j):
                    # Get the difference between the original advance width and
                    # the advance width after OTL.
                    kern = positions[k].advance - qh.Vector(adv, 0)

                    # Re-adjust glyph positions.
                    glyphs = [qh.Glyph(g.index, g.pos - kern) for g in glyphs]
                    nodes.append(
                        Box(self.doc, chars, glyphs, adv, stretch, shrink))

                    # Add glue with the kerning amount with minimal stretch and shrink.
                    nodes.append(
                        Glue(self.doc, kern.x, kern.x / 8.5, kern.x / 8.5))
                else:
                    nodes.append(
                        Box(self.doc, chars, glyphs, pos.x, stretch, shrink))
            elif pos.x != 0:
                # If space is not zero-width, add glue for it.
                nodes.append(Glue(self.doc, pos.x, pos.x / 8.5, pos.x / 8.5))

            i = j

        if mark:
            buf = self.shape(mark, hb.HARFBUZZ.DIRECTION_LTR)
            glyphs, pos = buf.get_glyphs()
            nodes.append(Box(self.doc, mark, glyphs, pos.x))

        return nodes