예제 #1
0
    def draw_chart(self):
        view_rect = Rect(0, 0, *self.view_size)
        title = self.title
        _, title_height = self.view.text_size(title, 1)
        titley = view_rect.h - title_height - self.PADDING
        title_rect = (0, titley, view_rect.w, title_height)
        self.view.draw_text(title, title_rect, FontID.Title)

        if not hasattr(self, 'pie1'):
            return

        # circle coords
        # circle_bounds is the area in which the circle is allowed to be drawn (important for legend text)
        circle_bounds = view_rect.scaled_rect(-self.PADDING, -self.PADDING)
        circle_bounds.h -= title_height

        if circle_bounds.w > circle_bounds.h:
            circle_bounds.w = (circle_bounds.w - self.PADDING) / 2
            circle_bounds2 = Rect(circle_bounds.right + self.PADDING,
                                  circle_bounds.y, circle_bounds.w,
                                  circle_bounds.h)
        else:
            circle_bounds.h = (circle_bounds.h - self.PADDING) / 2
            # We want the first circle to be on top
            circle_bounds.y += circle_bounds.h + self.PADDING
            # hscommon.geometry has a top-left origin, we use "top" when we mean "bottom".
            circle_bounds2 = Rect(
                circle_bounds.x,
                circle_bounds.top - circle_bounds.h - self.PADDING,
                circle_bounds.w, circle_bounds.h)

        self.draw_pie(self.pie1, circle_bounds)
        self.draw_pie(self.pie2, circle_bounds2)
예제 #2
0
 def draw_chart(self):
     view_rect = Rect(0, 0, *self.view_size)
     title = self.title
     _, title_height = self.view.text_size(title, 1)
     titley = view_rect.h - title_height - self.PADDING
     title_rect = (0, titley, view_rect.w, title_height)
     self.view.draw_text(title, title_rect, FontID.Title)
     
     if not hasattr(self, 'pie1'):
         return
     
     # circle coords
     # circle_bounds is the area in which the circle is allowed to be drawn (important for legend text)
     circle_bounds = view_rect.scaled_rect(-self.PADDING, -self.PADDING)
     circle_bounds.h -= title_height
     
     if circle_bounds.w > circle_bounds.h:
         circle_bounds.w = (circle_bounds.w - self.PADDING) / 2
         circle_bounds2 = Rect(circle_bounds.right + self.PADDING, circle_bounds.y,
             circle_bounds.w, circle_bounds.h)
     else:
         circle_bounds.h = (circle_bounds.h - self.PADDING) / 2
         # We want the first circle to be on top
         circle_bounds.y += circle_bounds.h + self.PADDING
         # hscommon.geometry has a top-left origin, we use "top" when we mean "bottom".
         circle_bounds2 = Rect(circle_bounds.x,
             circle_bounds.top - circle_bounds.h - self.PADDING, circle_bounds.w,
             circle_bounds.h)
     
     self.draw_pie(self.pie1, circle_bounds)
     self.draw_pie(self.pie2, circle_bounds2)
예제 #3
0
    def draw_graph(self, context):
        for x1, x2, h1, h2 in self.data:
            x1 *= context.xfactor
            x2 *= context.xfactor
            h1 *= context.yfactor
            h2 *= context.yfactor

            # Compute and fill past and future rectangles
            different_side = (h1 >= 0) != (h2 >= 0)
            past_rect = Rect(x1, 0, x2 - x1, abs(h1))
            if h2:
                future_height = abs(h2 if different_side else h2 - h1)
            else:
                future_height = 0
            future_rect = Rect(x1, 0, x2 - x1, future_height)
            if h1 >= 0:
                past_rect.bottom = h1
            else:
                past_rect.top = h1
            if h2 >= 0:
                future_rect.bottom = h2
            else:
                future_rect.top = h2
            self.view.draw_rect(context.trrect(past_rect), None,
                                BrushID.NormalBar)
            self.view.draw_rect(context.trrect(future_rect), None,
                                BrushID.FutureBar)

            # Compute and draw rect lines
            union = past_rect.united(future_rect)
            if (union.top < 0) and (union.bottom >
                                    0):  # we draw 4 sides instead of 3
                self.view.draw_rect(context.trrect(union), PenID.Bar, None)
            else:
                # One of bottom and top is 0. Use the other one. We're working with floats here,
                # comparison with 0 are hazardous, so I'm avoiding them.
                h = union.top if abs(union.top) >= abs(
                    union.bottom) else union.bottom
                points = [
                    Point(x1, 0),
                    Point(x1, h),
                    Point(x2, h),
                    Point(x2, 0)
                ]
                self.view.draw_polygon(context.trpoints(points), PenID.Bar,
                                       None)

            # draw red line
            if (h1 != 0) and (h2 != 0):
                lineY = 0 if different_side else h1
                p1 = context.trpoint(Point(x1, lineY))
                p2 = context.trpoint(Point(x2, lineY))
                context.today_line = (
                    p1, p2)  # will be drawn in draw_graph_after_axis()

        # We don't draw the X overlay in a bar graph
        self.draw_axis_overlay_y(context)
예제 #4
0
def create_element(layout_element):
    rect = Rect(layout_element.x0, layout_element.y0, layout_element.width,
                layout_element.height)
    chars = extract_chars(layout_element)
    fontsize = get_avg_text_height(chars)
    text = fix_text(layout_element.get_text())
    return TextElement(rect, fontsize, text)
예제 #5
0
 def _draw_mouse_selection(self):
     if self._last_mouse_down and self._last_mouse_pos:
         if self._reorder_mode:
             p1 = self._last_mouse_down
             p2 = self._last_mouse_pos
             linewidth = 5
             self.view.draw_arrow(Line(p1, p2), linewidth, PageColor.MouseSelection)
         else:
             r = Rect.from_corners(self._last_mouse_down, self._last_mouse_pos)
             self.view.draw_rectangle(r, None, PageColor.MouseSelection)
예제 #6
0
 def _handle_drag_completion(self):
     if self._reorder_mode:
         reorder_line = Line(self._last_mouse_down, self._last_mouse_pos)
         if self.shift_key_held:
             self._reorder_line_buffer.append(reorder_line)
         else:
             self._reorder_following_line([reorder_line])
     else:
         r = Rect.from_corners(self._last_mouse_down, self._last_mouse_pos)
         self._select_elems_in_rect(r)
예제 #7
0
 def _draw_mouse_selection(self):
     if self._last_mouse_down and self._last_mouse_pos:
         if self._reorder_mode:
             p1 = self._last_mouse_down
             p2 = self._last_mouse_pos
             linewidth = 5
             self.view.draw_arrow(Line(p1, p2), linewidth, PageColor.MouseSelection)
         else:
             r = Rect.from_corners(self._last_mouse_down, self._last_mouse_pos)
             self.view.draw_rectangle(r, None, PageColor.MouseSelection)
예제 #8
0
 def _handle_drag_completion(self):
     if self._reorder_mode:
         reorder_line = Line(self._last_mouse_down, self._last_mouse_pos)
         if self.shift_key_held:
             self._reorder_line_buffer.append(reorder_line)
         else:
             self._reorder_following_line([reorder_line])
     else:
         r = Rect.from_corners(self._last_mouse_down, self._last_mouse_pos)
         self._select_elems_in_rect(r)
예제 #9
0
 def _draw_order_arrows(self):
     elems = list(self._ordered_elems())
     if not elems:
         return
     # mark the starting pos
     firstelem = elems[0]
     center = self._elem2drawrect[firstelem].center()
     r = Rect.from_center(center, 10, 10)
     self.view.draw_rectangle(r, PageColor.ElemOrderArrow, None)
     linewidth = 1
     for elem1, elem2 in trailiter(elems, skipfirst=True):
         p1 = self._elem2drawrect[elem1].center()
         p2 = self._elem2drawrect[elem2].center()
         self.view.draw_arrow(Line(p1, p2), linewidth, PageColor.ElemOrderArrow)
     linewidth = 5
     for line in self._reorder_line_buffer:
         self.view.draw_arrow(line, linewidth, PageColor.ElemOrderArrow)
예제 #10
0
 def _draw_order_arrows(self):
     elems = list(self._ordered_elems())
     if not elems:
         return
     # mark the starting pos
     firstelem = elems[0]
     center = self._elem2drawrect[firstelem].center()
     r = Rect.from_center(center, 10, 10)
     self.view.draw_rectangle(r, PageColor.ElemOrderArrow, None)
     linewidth = 1
     for elem1, elem2 in trailiter(elems, skipfirst=True):
         p1 = self._elem2drawrect[elem1].center()
         p2 = self._elem2drawrect[elem2].center()
         self.view.draw_arrow(Line(p1, p2), linewidth, PageColor.ElemOrderArrow)
     linewidth = 5
     for line in self._reorder_line_buffer:
         self.view.draw_arrow(line, linewidth, PageColor.ElemOrderArrow)
예제 #11
0
 def draw_graph(self, context):
     for x1, x2, h1, h2 in self.data:
         x1 *= context.xfactor
         x2 *= context.xfactor
         h1 *= context.yfactor
         h2 *= context.yfactor
         
         # Compute and fill past and future rectangles
         different_side = (h1 >= 0) != (h2 >= 0)
         past_rect = Rect(x1, 0, x2-x1, abs(h1))
         if h2:
             future_height = abs(h2 if different_side else h2-h1)
         else:
             future_height = 0
         future_rect = Rect(x1, 0, x2-x1, future_height)
         if h1 >= 0:
             past_rect.bottom = h1
         else:
             past_rect.top = h1
         if h2 >= 0:
             future_rect.bottom = h2
         else:
             future_rect.top = h2            
         self.view.draw_rect(context.trrect(past_rect), None, BrushID.NormalBar)
         self.view.draw_rect(context.trrect(future_rect), None, BrushID.FutureBar)
         
         # Compute and draw rect lines
         union = past_rect.united(future_rect)
         if (union.top < 0) and (union.bottom > 0): # we draw 4 sides instead of 3
             self.view.draw_rect(context.trrect(union), PenID.Bar, None)
         else:
             # One of bottom and top is 0. Use the other one. We're working with floats here,
             # comparison with 0 are hazardous, so I'm avoiding them.
             h = union.top if abs(union.top) >= abs(union.bottom) else union.bottom
             points = [Point(x1, 0), Point(x1, h), Point(x2, h), Point(x2, 0)]
             self.view.draw_polygon(context.trpoints(points), PenID.Bar, None)
         
         
         # draw red line
         if (h1 != 0) and (h2 != 0):
             lineY = 0 if different_side else h1
             p1 = context.trpoint(Point(x1, lineY))
             p2 = context.trpoint(Point(x2, lineY))
             context.today_line = (p1, p2) # will be drawn in draw_graph_after_axis()
     
     # We don't draw the X overlay in a bar graph
     self.draw_axis_overlay_y(context)
예제 #12
0
 def _compute_elem_drawrect(self, page_boundaries):
     if self._last_page_boundaries == page_boundaries:
         return
     self._last_page_boundaries = page_boundaries
     px, py, pw, ph = page_boundaries
     self._elem2drawrect = {}
     xratio = pw / self.page.width
     yratio = ph / self.page.height
     for elem in self.elements:
         if elem.state == ElementState.Ignored and self.app.hide_ignored:
             continue # we don't draw the elem
         rect = elem.rect
         adjx = px + (rect.x * xratio)
         # don't forget that ypos in pdfminer are inverted
         adjy = py + (ph - ((rect.y+rect.h) * yratio))
         adjw = rect.w * xratio
         adjh = rect.h * yratio
         self._elem2drawrect[elem] = Rect(adjx, adjy, adjw, adjh)
예제 #13
0
 def trrect(self, r):
     x, y, w, h = r
     x += self.xoffset
     y += self.yoffset
     return Rect(x, y, w, h)
예제 #14
0
    def draw_chart(self):
        if not hasattr(self, 'xmax'):  # we haven't computed yet
            return
        view_rect = Rect(0, 0, *self.view_size)
        data_width = self.xmax - self.xmin
        data_height = self.ymax - self.ymin
        y_labels_width = max(
            self.view.text_size(label['text'], FontID.AxisLabel)[0]
            for label in self.ylabels)
        labels_height = self.view.text_size('', FontID.AxisLabel)[1]
        title = "{} ({})".format(self.title, self.currency.code)
        title_width, title_height = self.view.text_size(title, FontID.Title)
        titley = view_rect.h - self.TITLE_PADDING - title_height
        graphx = y_labels_width + self.PADDING
        graphy = labels_height + self.PADDING
        graph_width = view_rect.w - graphx - self.PADDING
        graph_height = view_rect.h - graphy - title_height - self.TITLE_PADDING
        graph_rect = Rect(graphx, graphy, graph_width, graph_height)
        xfactor = graph_width / data_width
        yfactor = graph_height / data_height
        graph_left = round(self.xmin * xfactor)
        graph_bottom = round(self.ymin * yfactor)
        if graph_bottom < 0:
            # We have a graph with negative values and we need some extra space to draw the lowest values
            graph_bottom -= self.YAXIS_EXTRA_SPACE_ON_NEGATIVE
        graph_top = round(self.ymax * yfactor)
        xoffset = graph_rect.left
        yoffset = -(graph_bottom - graph_rect.y)
        context = GraphContext(xfactor, yfactor, xoffset, yoffset)

        self.draw_graph(context)

        # X/Y axis
        p1 = context.trpoint(Point(0, graph_bottom))
        p2 = context.trpoint(Point(graph_width, graph_bottom))
        p3 = context.trpoint(Point(0, graph_top))
        self.view.draw_line(p1, p2, PenID.Axis)
        self.view.draw_line(p1, p3, PenID.Axis)
        if graph_bottom < 0:
            p1 = context.trpoint(Point(0, 0))
            p2 = context.trpoint(Point(graph_width, 0))
            self.view.draw_line(p1, p2, PenID.Axis)

        # X tickmarks
        tickBottomY = graph_bottom - self.TICKMARKS_LENGTH
        for tickPos in self.xtickmarks:
            tickX = tickPos * xfactor
            p1 = context.trpoint(Point(tickX, graph_bottom))
            p2 = context.trpoint(Point(tickX, tickBottomY))
            self.view.draw_line(p1, p2, PenID.Axis)

        # Y tickmarks
        tickLeftX = graph_left - self.TICKMARKS_LENGTH
        for tickPos in self.ytickmarks:
            tickY = tickPos * yfactor
            p1 = context.trpoint(Point(graph_left, tickY))
            p2 = context.trpoint(Point(tickLeftX, tickY))
            self.view.draw_line(p1, p2, PenID.Axis)

        # X Labels
        labelY = graph_bottom - labels_height - self.XLABELS_PADDING
        for label in self.xlabels:
            labelText = label['text']
            labelWidth = self.view.text_size(labelText, FontID.AxisLabel)[0]
            labelX = (label['pos'] * xfactor) - (labelWidth / 2)
            text_rect = context.trrect(
                Rect(labelX, labelY, labelWidth, labels_height))
            self.view.draw_text(labelText, text_rect, FontID.AxisLabel)

        # Y Labels
        for label in self.ylabels:
            labelText = label['text']
            labelWidth = self.view.text_size(labelText, FontID.AxisLabel)[0]
            labelX = graph_left - self.YLABELS_PADDING - labelWidth
            labelY = (label['pos'] * yfactor) - (labels_height / 2)
            text_rect = context.trrect(
                Rect(labelX, labelY, labelWidth, labels_height))
            self.view.draw_text(labelText, text_rect, FontID.AxisLabel)

        # Title
        self.view.draw_text(title, Rect(0, titley, view_rect.w, title_height),
                            FontID.Title)

        self.draw_graph_after_axis(context)
예제 #15
0
def rect_from_center(center, size):
    # Returns a Rect centered on `center` with size `size`
    w, h = size
    x = center.x - w / 2
    y = center.y - h / 2
    return Rect(x, y, w, h)
예제 #16
0
 def str2rect(s):
     elems = s.split(' ')
     assert len(elems) == 4
     return Rect(*map(float, elems))