From a380c204d6c390152aab64e31b262ca6ad01c5b5 Mon Sep 17 00:00:00 2001 From: Boushrabnd Date: Mon, 4 Dec 2023 15:05:27 +0300 Subject: [PATCH 01/21] Added set_fill_pattern() function to fpdf.py --- fpdf/fpdf.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index 391a67ab9..2d7f312ff 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -263,6 +263,7 @@ def __init__( self.page = 0 # current page number self.pages = {} # array of PDFPage objects starting at index 1 self.fonts = {} # map font string keys to an instance of CoreFont or TTFFont + self.patterns = {} # map pattern fill objects self.links = {} # array of Destination objects starting at index 1 self.embedded_files = [] # array of PDFEmbeddedFile self.image_cache = ImageCache() @@ -311,6 +312,7 @@ def __init__( ) self.draw_color = self.DEFAULT_DRAW_COLOR self.fill_color = self.DEFAULT_FILL_COLOR + self.fill_pattern = self.DEFAULT_FILL_PATTERN self.text_color = self.DEFAULT_TEXT_COLOR self.page_background = None self.dash_pattern = dict(dash=0, gap=0, phase=0) @@ -1018,6 +1020,24 @@ def set_fill_color(self, r, g=-1, b=-1): self.fill_color = convert_to_device_color(r, g, b) if self.page > 0: self._out(self.fill_color.serialize().lower()) + + def set_fill_pattern(self): + """ + Defines the pattern used for all filling operations (filled rectangles and cell backgrounds). + It can be expressed in RGB components or grey scale. + The method can be called before the first page is created and the value is retained from page to page. + + Args: + r (int, tuple, fpdf.drawing.DeviceGray, fpdf.drawing.DeviceRGB): if `g` and `b` are given, this indicates the red component. + Else, this indicates the grey level. The value must be between 0 and 255. + g (int): green component (between 0 and 255) + b (int): blue component (between 0 and 255) + """ + print("Hello") + print(self.fill_pattern) + if self.page > 0: + print(self.fill_pattern.serialize().lower()) + self._out(self.fill_pattern.serialize()) def set_text_color(self, r, g=-1, b=-1): """ @@ -2581,6 +2601,7 @@ def local_context( line_width=None, draw_color=None, fill_color=None, + fill_pattern=None, text_color=None, dash_pattern=None, **kwargs, @@ -2664,6 +2685,8 @@ def local_context( self.set_draw_color(draw_color) if fill_color is not None: self.set_fill_color(fill_color) + if fill_pattern is not None: + self.set_fill_pattern(fill_pattern) if text_color is not None: self.set_text_color(text_color) if dash_pattern is not None: From dbad42f248982b4c3e175696274e4dafa943ae71 Mon Sep 17 00:00:00 2001 From: Boushrabnd Date: Mon, 4 Dec 2023 15:11:02 +0300 Subject: [PATCH 02/21] Added Tilling Pattern Object (experiment) --- fpdf/drawing.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/fpdf/drawing.py b/fpdf/drawing.py index adcb3ff51..548a0f34d 100644 --- a/fpdf/drawing.py +++ b/fpdf/drawing.py @@ -1085,6 +1085,7 @@ class GraphicsStyle: "intersection_rule", "fill_color", "fill_opacity", + "fill_pattern", "stroke_color", "stroke_opacity", "blend_mode", @@ -1149,6 +1150,7 @@ def __init__(self): self.intersection_rule = self.INHERIT self.fill_color = self.INHERIT self.fill_opacity = self.INHERIT + self.fill_pattern = self.INHERIT self.stroke_color = self.INHERIT self.stroke_opacity = self.INHERIT self.blend_mode = self.INHERIT @@ -1264,6 +1266,17 @@ def fill_opacity(self, new): super().__setattr__(PDFStyleKeys.FILL_ALPHA.value, new) + @property + def fill_pattern(self): + """The desired fill pattern for this path/group.""" + pass + + @fill_pattern.setter + def fill_pattern(self, new): + """The desired fill pattern for this path/group.""" + pass + + @property def stroke_color(self): """ @@ -4206,3 +4219,17 @@ def render_debug( pfx, _push_stack=_push_stack, ) + +class TilingPattern: + def __init__(self, pattern_type=1, paint_type=1, tiling_type=1, bbox=[0, 0, 10, 10], x_step= 20, y_step=20, resources=None, matrix=None): + self.pattern_type = pattern_type + self.paint_type = paint_type + self.tiling_type = tiling_type + self.bbox = bbox + self.x_step = x_step + self.y_step = y_step + self.resources = resources if resources is not None else {} + self.matrix = matrix if matrix is not None else [1, 0, 0, 1, 0, 0] + + def serialize(self): + return "/Pattern cs /P1 scn" # place holder to be fixed From 7b1877dcff462be6284cd18e23485bd3ae50ff5d Mon Sep 17 00:00:00 2001 From: Boushrabnd Date: Mon, 4 Dec 2023 15:13:36 +0300 Subject: [PATCH 03/21] Added default pattern to be tilling (experiment) --- fpdf/graphics_state.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fpdf/graphics_state.py b/fpdf/graphics_state.py index 450e259cc..b16db7b68 100644 --- a/fpdf/graphics_state.py +++ b/fpdf/graphics_state.py @@ -6,7 +6,7 @@ in non-backward-compatible ways. """ -from .drawing import DeviceGray +from .drawing import DeviceGray, TilingPattern from .enums import CharVPos, TextEmphasis, TextMode from .fonts import FontFace @@ -26,6 +26,7 @@ class GraphicsStateMixin: DEFAULT_DRAW_COLOR = DeviceGray(0) DEFAULT_FILL_COLOR = DeviceGray(0) DEFAULT_TEXT_COLOR = DeviceGray(0) + DEFAULT_FILL_PATTERN = TilingPattern() def __init__(self, *args, **kwargs): self.__statestack = [ From 6cde5d2edaac284c7d73ae9f5c174f5d95ab191b Mon Sep 17 00:00:00 2001 From: Boushrabnd Date: Mon, 4 Dec 2023 15:16:53 +0300 Subject: [PATCH 04/21] Added PDFPattern Object to be outputed in PDF --- fpdf/output.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/fpdf/output.py b/fpdf/output.py index 9cd2c1274..fa5b916a1 100644 --- a/fpdf/output.py +++ b/fpdf/output.py @@ -77,6 +77,18 @@ def __init__(self, subtype, base_font, encoding=None, d_w=None, w=None): self.font_descriptor = None self.c_i_d_to_g_i_d_map = None +class PDFPattern(PDFObject): + def __init__(self, pattern_type, paint_type, tiling_type, bbox, x_step, y_step, resources=None, matrix=None): + super().__init__() + self.type = Name("Pattern") + self.pattern_type = pattern_type + self.paint_type = paint_type + self.tiling_type = tiling_type + self.bbox = bbox + self.x_step = x_step + self.y_step = y_step + self.resources = resources if resources else None + self.matrix = matrix if matrix else None class CIDSystemInfo(PDFObject): def __init__(self): @@ -377,6 +389,7 @@ def bufferize(self): for embedded_file in fpdf.embedded_files: self._add_pdf_obj(embedded_file, "embedded_files") font_objs_per_index = self._add_fonts() + # pattern_objs_per_index = self._add_patterns() img_objs_per_index = self._add_images() gfxstate_objs_per_name = self._add_gfxstates() resources_dict_obj = self._add_resources_dict( @@ -690,6 +703,25 @@ def format_code(unicode): font.close() return font_objs_per_index + + def _add_patterns(self): + print("adding patterns") + pattern_objs_per_index = {} + for pattern in sorted(self.patterns.values(), key=lambda pattern: pattern.i): + # Assuming each pattern has an index and necessary properties + # Define a tiling pattern + tiling_pattern_obj = PDFPattern( + pattern_type=1, # Tiling pattern + paint_type=1, # Colored tiling pattern + tiling_type=1, # Constant spacing + bbox=[0, 0, 8, 8], # The pattern cell's bounding box + x_step=12, # Horizontal spacing + y_step=12 # Vertical spacing + # Resources and matrix could be added if necessary + ) + self._add_pdf_obj(tiling_pattern_obj, "patterns") + pattern_objs_per_index[pattern.i] = tiling_pattern_obj + def _add_images(self): img_objs_per_index = {} From 08f6c34cd228d66e859994de22353b6231f745bf Mon Sep 17 00:00:00 2001 From: Boushrabnd Date: Mon, 4 Dec 2023 16:09:28 +0300 Subject: [PATCH 05/21] Pylint and Black --- fpdf/drawing.py | 34 ++++++++++++++++++++++------------ fpdf/fpdf.py | 6 +++--- fpdf/output.py | 25 ++++++++++++++++++------- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/fpdf/drawing.py b/fpdf/drawing.py index 548a0f34d..53c4c2ff4 100644 --- a/fpdf/drawing.py +++ b/fpdf/drawing.py @@ -1275,7 +1275,6 @@ def fill_pattern(self): def fill_pattern(self, new): """The desired fill pattern for this path/group.""" pass - @property def stroke_color(self): @@ -4219,17 +4218,28 @@ def render_debug( pfx, _push_stack=_push_stack, ) - + + class TilingPattern: - def __init__(self, pattern_type=1, paint_type=1, tiling_type=1, bbox=[0, 0, 10, 10], x_step= 20, y_step=20, resources=None, matrix=None): - self.pattern_type = pattern_type - self.paint_type = paint_type - self.tiling_type = tiling_type - self.bbox = bbox - self.x_step = x_step - self.y_step = y_step - self.resources = resources if resources is not None else {} - self.matrix = matrix if matrix is not None else [1, 0, 0, 1, 0, 0] + def __init__( + self, + pattern_type=1, + paint_type=1, + tiling_type=1, + bbox=[0, 0, 10, 10], + x_step=20, + y_step=20, + resources=None, + matrix=None, + ): + self.pattern_type = pattern_type + self.paint_type = paint_type + self.tiling_type = tiling_type + self.bbox = bbox + self.x_step = x_step + self.y_step = y_step + self.resources = resources if resources is not None else {} + self.matrix = matrix if matrix is not None else [1, 0, 0, 1, 0, 0] def serialize(self): - return "/Pattern cs /P1 scn" # place holder to be fixed + return "/Pattern cs /P1 scn" # place holder to be fixed diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index 2d7f312ff..2be725974 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -263,7 +263,7 @@ def __init__( self.page = 0 # current page number self.pages = {} # array of PDFPage objects starting at index 1 self.fonts = {} # map font string keys to an instance of CoreFont or TTFFont - self.patterns = {} # map pattern fill objects + self.patterns = {} # map pattern fill objects self.links = {} # array of Destination objects starting at index 1 self.embedded_files = [] # array of PDFEmbeddedFile self.image_cache = ImageCache() @@ -1020,7 +1020,7 @@ def set_fill_color(self, r, g=-1, b=-1): self.fill_color = convert_to_device_color(r, g, b) if self.page > 0: self._out(self.fill_color.serialize().lower()) - + def set_fill_pattern(self): """ Defines the pattern used for all filling operations (filled rectangles and cell backgrounds). @@ -2686,7 +2686,7 @@ def local_context( if fill_color is not None: self.set_fill_color(fill_color) if fill_pattern is not None: - self.set_fill_pattern(fill_pattern) + self.set_fill_pattern() if text_color is not None: self.set_text_color(text_color) if dash_pattern is not None: diff --git a/fpdf/output.py b/fpdf/output.py index fa5b916a1..04a14ec9c 100644 --- a/fpdf/output.py +++ b/fpdf/output.py @@ -77,8 +77,19 @@ def __init__(self, subtype, base_font, encoding=None, d_w=None, w=None): self.font_descriptor = None self.c_i_d_to_g_i_d_map = None + class PDFPattern(PDFObject): - def __init__(self, pattern_type, paint_type, tiling_type, bbox, x_step, y_step, resources=None, matrix=None): + def __init__( + self, + pattern_type, + paint_type, + tiling_type, + bbox, + x_step, + y_step, + resources=None, + matrix=None, + ): super().__init__() self.type = Name("Pattern") self.pattern_type = pattern_type @@ -90,6 +101,7 @@ def __init__(self, pattern_type, paint_type, tiling_type, bbox, x_step, y_step, self.resources = resources if resources else None self.matrix = matrix if matrix else None + class CIDSystemInfo(PDFObject): def __init__(self): super().__init__() @@ -703,7 +715,7 @@ def format_code(unicode): font.close() return font_objs_per_index - + def _add_patterns(self): print("adding patterns") pattern_objs_per_index = {} @@ -712,17 +724,16 @@ def _add_patterns(self): # Define a tiling pattern tiling_pattern_obj = PDFPattern( pattern_type=1, # Tiling pattern - paint_type=1, # Colored tiling pattern - tiling_type=1, # Constant spacing + paint_type=1, # Colored tiling pattern + tiling_type=1, # Constant spacing bbox=[0, 0, 8, 8], # The pattern cell's bounding box - x_step=12, # Horizontal spacing - y_step=12 # Vertical spacing + x_step=12, # Horizontal spacing + y_step=12 # Vertical spacing # Resources and matrix could be added if necessary ) self._add_pdf_obj(tiling_pattern_obj, "patterns") pattern_objs_per_index[pattern.i] = tiling_pattern_obj - def _add_images(self): img_objs_per_index = {} for img in sorted( From 38cfca1bf08e61665e3026b1dc683957e75199ee Mon Sep 17 00:00:00 2001 From: Boushrabnd Date: Mon, 4 Dec 2023 18:46:48 +0300 Subject: [PATCH 06/21] Fixing pylint errors and black formatting --- Expolration_set_pattern.py | 52 ++++++++++++++++------------------- Working_function_rect_circ.py | 10 ++++--- fpdf/drawing.py | 18 +++--------- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/Expolration_set_pattern.py b/Expolration_set_pattern.py index c039e7486..d6b51c5dc 100644 --- a/Expolration_set_pattern.py +++ b/Expolration_set_pattern.py @@ -4,44 +4,40 @@ pdf = FPDF() # Add a page -r= pdf.add_page() +pdf.add_page() # Set fill color (RGB) pdf.set_fill_color(255, 205, 0) # Setting the color to red -#pdf.set_page_background('/Users/lamamasri/Desktop/image_13.gif') -w1=10 -w2=10 -w3=50 -w4=40 -pdf.rect(10,10,50,30) - -n=0 -while n<=50: - - - pdf.rect(w1, w2,w3/10, w3/10, 'F') - pdf.rect(w1, w2+10,w3/10, w3/10, 'F') - pdf.rect(w1, w2+20,w3/10, w3/10, 'F') - pdf.rect(w1, w2+28,w3/10, w3/10, 'F') - w1=w1+w3/5 - - n=n+10 - print("N1: ",n) +# pdf.set_page_background('/Users/lamamasri/Desktop/image_13.gif') +w1 = 10 +w2 = 10 +w3 = 50 +w4 = 40 +pdf.rect(10, 10, 50, 30) + +n = 0 +while n <= 50: + pdf.rect(w1, w2, w3 / 10, w3 / 10, "F") + pdf.rect(w1, w2 + 10, w3 / 10, w3 / 10, "F") + pdf.rect(w1, w2 + 20, w3 / 10, w3 / 10, "F") + pdf.rect(w1, w2 + 28, w3 / 10, w3 / 10, "F") + w1 = w1 + w3 / 5 + + n = n + 10 + print("N1: ", n) print("W1; ,", w1) # Draw a filled rectangle -#for i in range (w3): - #pdf.rect(w1, w2,w3/10, w3/10, 'F') - -#pdf.rect(10, 10, 5, 5, 'F') # 'F' argument is for fill +# for i in range (w3): +# pdf.rect(w1, w2,w3/10, w3/10, 'F') -#pdf.rect(20, 10, 5, 5, 'F') - -#pdf.rect(30, 10, 5, 5, 'F') +# pdf.rect(10, 10, 5, 5, 'F') # 'F' argument is for fill +# pdf.rect(20, 10, 5, 5, 'F') +# pdf.rect(30, 10, 5, 5, 'F') # Output the PDF -pdf.output('filled_rectangle.pdf') \ No newline at end of file +pdf.output("filled_rectangle.pdf") diff --git a/Working_function_rect_circ.py b/Working_function_rect_circ.py index 6e0ce3a18..59d1846d3 100644 --- a/Working_function_rect_circ.py +++ b/Working_function_rect_circ.py @@ -10,7 +10,9 @@ # Draw the outer rectangle outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h = 10, 10, 50, 30 -pdf.ellipse(outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h, 'F') # Fill the outer rectangle +pdf.ellipse( + outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h, "F" +) # Fill the outer rectangle # Pattern properties pattern_width, pattern_height = 5, 10 # Width and height of the small rectangles @@ -26,10 +28,10 @@ if (i + j) % 2 == 0: # Check for alternate placement x = outer_rect_x + i * pattern_width y = outer_rect_y + j * pattern_height - pdf.rect(x, y, pattern_width, pattern_height, 'F') - + pdf.rect(x, y, pattern_width, pattern_height, "F") + pdf.set_draw_color(0, 0, 0) # Black border pdf.ellipse(outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h) # Output the PDF -pdf.output('pattern_filled_rectangle.pdf') \ No newline at end of file +pdf.output("pattern_filled_rectangle.pdf") diff --git a/fpdf/drawing.py b/fpdf/drawing.py index 53c4c2ff4..84453f691 100644 --- a/fpdf/drawing.py +++ b/fpdf/drawing.py @@ -1266,16 +1266,6 @@ def fill_opacity(self, new): super().__setattr__(PDFStyleKeys.FILL_ALPHA.value, new) - @property - def fill_pattern(self): - """The desired fill pattern for this path/group.""" - pass - - @fill_pattern.setter - def fill_pattern(self, new): - """The desired fill pattern for this path/group.""" - pass - @property def stroke_color(self): """ @@ -4226,7 +4216,7 @@ def __init__( pattern_type=1, paint_type=1, tiling_type=1, - bbox=[0, 0, 10, 10], + bbox=None, x_step=20, y_step=20, resources=None, @@ -4235,11 +4225,11 @@ def __init__( self.pattern_type = pattern_type self.paint_type = paint_type self.tiling_type = tiling_type - self.bbox = bbox + self.bbox = bbox if bbox is not None else [0, 0, 10, 10] self.x_step = x_step self.y_step = y_step self.resources = resources if resources is not None else {} self.matrix = matrix if matrix is not None else [1, 0, 0, 1, 0, 0] - - def serialize(self): + @staticmethod # remove once the serialize is fully implememented + def serialize(): return "/Pattern cs /P1 scn" # place holder to be fixed From ec390b9c593b96d8dccbf11e4993dc340281297f Mon Sep 17 00:00:00 2001 From: Jamil Daoud Date: Mon, 4 Dec 2023 19:46:35 +0300 Subject: [PATCH 07/21] Developed basic function that works but not a 100% and only works on rectangles --- Exploration_set_pattern.py | 47 ++++++++++++++++++++++++++++++++ Working_function_rect_circ.py | 35 ++++++++++++++++++++++++ test/image/filled_rectangle.pdf | Bin 0 -> 927 bytes 3 files changed, 82 insertions(+) create mode 100644 Exploration_set_pattern.py create mode 100644 Working_function_rect_circ.py create mode 100644 test/image/filled_rectangle.pdf diff --git a/Exploration_set_pattern.py b/Exploration_set_pattern.py new file mode 100644 index 000000000..c039e7486 --- /dev/null +++ b/Exploration_set_pattern.py @@ -0,0 +1,47 @@ +from fpdf import FPDF + +# Create instance of FPDF class +pdf = FPDF() + +# Add a page +r= pdf.add_page() + +# Set fill color (RGB) +pdf.set_fill_color(255, 205, 0) # Setting the color to red + +#pdf.set_page_background('/Users/lamamasri/Desktop/image_13.gif') +w1=10 +w2=10 +w3=50 +w4=40 +pdf.rect(10,10,50,30) + +n=0 +while n<=50: + + + pdf.rect(w1, w2,w3/10, w3/10, 'F') + pdf.rect(w1, w2+10,w3/10, w3/10, 'F') + pdf.rect(w1, w2+20,w3/10, w3/10, 'F') + pdf.rect(w1, w2+28,w3/10, w3/10, 'F') + w1=w1+w3/5 + + n=n+10 + print("N1: ",n) + print("W1; ,", w1) + +# Draw a filled rectangle +#for i in range (w3): + #pdf.rect(w1, w2,w3/10, w3/10, 'F') + +#pdf.rect(10, 10, 5, 5, 'F') # 'F' argument is for fill + +#pdf.rect(20, 10, 5, 5, 'F') + +#pdf.rect(30, 10, 5, 5, 'F') + + + + +# Output the PDF +pdf.output('filled_rectangle.pdf') \ No newline at end of file diff --git a/Working_function_rect_circ.py b/Working_function_rect_circ.py new file mode 100644 index 000000000..6e0ce3a18 --- /dev/null +++ b/Working_function_rect_circ.py @@ -0,0 +1,35 @@ +from fpdf import FPDF + +pdf = FPDF() + +# Add a page +pdf.add_page() + +# Set fill color (RGB) +pdf.set_fill_color(255, 205, 0) # Setting the color to yellow + +# Draw the outer rectangle +outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h = 10, 10, 50, 30 +pdf.ellipse(outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h, 'F') # Fill the outer rectangle + +# Pattern properties +pattern_width, pattern_height = 5, 10 # Width and height of the small rectangles +cols = int(outer_rect_w / pattern_width) # Number of small rectangles horizontally +rows = int(outer_rect_h / pattern_height) # Number of small rectangles vertically + +# Set color for the pattern +pdf.set_fill_color(255, 255, 255) # White for the spacing + +# Create the pattern +for i in range(cols): + for j in range(rows): + if (i + j) % 2 == 0: # Check for alternate placement + x = outer_rect_x + i * pattern_width + y = outer_rect_y + j * pattern_height + pdf.rect(x, y, pattern_width, pattern_height, 'F') + +pdf.set_draw_color(0, 0, 0) # Black border +pdf.ellipse(outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h) + +# Output the PDF +pdf.output('pattern_filled_rectangle.pdf') \ No newline at end of file diff --git a/test/image/filled_rectangle.pdf b/test/image/filled_rectangle.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f83d9a4b8f88e6605547be035e0dec29794e6549 GIT binary patch literal 927 zcmZWo&ubGw6!xNrLA)01R#hu+vH=CAFv`M#yR@0_Eh&AYDcam=1?1bHkB!Yri z>BXZ$@mCKD3M%#=C~8HEpe+=IsJ)2bE!abQDk;viNgM65?Ci{&_r3YP?@ilq+&G~~ zArt}`Xl4>cqj;=bAb^L>96|i+6OVzyqbY<_B%np#A_1s73o+_39uJ^P%zJwg@oa%2 zrgb#KaT)Oe8?MPnoLJQ6;6udAu?bMZD$fa+Ps}_jJ-D`_99fVL-}*WKbnW2ex5Vm9 z=bV4&(w~J5rIJ4RYVhdB<@L_Ht?3r?{`&bl{ZmtE%zT2_p9zr*1ml9dF!IS z`Otg4)Z=^}SbJRhaO2oa-qJtSHh<6ls$6+nwJVZQ&3sw9c;Ls!x%BPt@1MOKsUB~^ z(;M$bwhEPH{Bg3c+jx}7#EtR zAdPU07KMlipCPtm_R$iI%RHuaYmyp)NS7i-y3=S+KB4XoEO)@C)+k{xj=5EU$4H3* zPUN{eef2R`9}~Qi!3}|ERAAwA$;>3N8q+;=?O$}eXmNkqhs%a2ph&u;!USW59*hg+ zY{AY-IZAWxwsVq2^SFZ(;*K$gdU5V4w8wi?Sq&+w98wjPza33f!cE0?8Y^Zp)1^7l zTRGlI_0~!jhq;jq)-6-RL zw2%f_Xsm^lZrF~3x4YIQ^8<>fX-$^*?~^0?zI__c`ad_^oXdREaf#3G6vCsY)2KozVmnWS7 literal 0 HcmV?d00001 From 477b0c4ce91682204486d80c8ae0243b5a894482 Mon Sep 17 00:00:00 2001 From: Jamil Daoud Date: Mon, 4 Dec 2023 19:51:44 +0300 Subject: [PATCH 08/21] Developed a more complex function that produces patterns of rectangles, squares, and circles in eitheran outer shape of a rectangle or a circle --- pattern_filled_rectangle.pdf | Bin 0 -> 981 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pattern_filled_rectangle.pdf diff --git a/pattern_filled_rectangle.pdf b/pattern_filled_rectangle.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3092d0072ff0ad579afee8a792176140b10b7420 GIT binary patch literal 981 zcmZWoTS!zv7)BooCR2it)?_@xHn%60L&Av$N~U?wRH6Z0QQV zXevYomJfvyK@voC#SDAWim-=@$O?QgiL%REFJc?fjINh-9?tOpbLRW!`@a9rZFIQ{ z4T1@npa@Av7qHt=b59II)To3oU|$_;6dKs67a%W=lZ39~I5e&&oJ6DSJPyq~E-eLE z3vd)3rqSHt2*o-??ubIM3#%l+!0WIUqMguaklCF$)v*!<-Q)A4hU}*>tMW|4(!O`I zdsM4q;!a6sS8-zQ?avQ|BbRE9^&Wn<@&YYp4Au_kgS+KN)PZ3s=r2osIZze#JLX#l z^KMV$gPAplE|yOWj9!-lrz&%vH~cuU+WTgqH7l4SJnYLJ5hky=@}|Gdlr1OE8-Mrp zpMIROFU)^kinhP30ymrd+WXHRJ7MnnSi({nt(d3vsl+z2QGH$(EYMDBBd3LDe zZ0g$h%-p^2a609)-*2n1eF|07@BOp%diD6n>|YmFl7APMll#e&s}Fo!lQhM&I$X_N zTE_vZ4F}@T&zxCO$MWAHrUKI zlUT5gioC7ZdOJE5szgYLcVvk5U%DYZF|0XMj=7;5a))UZ)Dn>hueGM@`aO_Jr8*ap^%HhhOk--63E@~awc)A=yZ*TMV3KsZl%W!{sCsD BHXr~1 literal 0 HcmV?d00001 From 7442c47a0658f9b76cbf4c8767c535281d718431 Mon Sep 17 00:00:00 2001 From: Jamil Daoud Date: Tue, 5 Dec 2023 12:37:01 +0300 Subject: [PATCH 09/21] Developed basic function that works but not a 100% and only works on rectangles --- ...t_pattern.py => Expolration_set_pattern.py | 0 Working_function_rect_circ.py | 35 ------------------ ...lled_rectangle.pdf => filled_rectangle.pdf | Bin pattern_filled_rectangle.pdf | Bin 981 -> 0 bytes 4 files changed, 35 deletions(-) rename Exploration_set_pattern.py => Expolration_set_pattern.py (100%) delete mode 100644 Working_function_rect_circ.py rename test/image/filled_rectangle.pdf => filled_rectangle.pdf (100%) delete mode 100644 pattern_filled_rectangle.pdf diff --git a/Exploration_set_pattern.py b/Expolration_set_pattern.py similarity index 100% rename from Exploration_set_pattern.py rename to Expolration_set_pattern.py diff --git a/Working_function_rect_circ.py b/Working_function_rect_circ.py deleted file mode 100644 index 6e0ce3a18..000000000 --- a/Working_function_rect_circ.py +++ /dev/null @@ -1,35 +0,0 @@ -from fpdf import FPDF - -pdf = FPDF() - -# Add a page -pdf.add_page() - -# Set fill color (RGB) -pdf.set_fill_color(255, 205, 0) # Setting the color to yellow - -# Draw the outer rectangle -outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h = 10, 10, 50, 30 -pdf.ellipse(outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h, 'F') # Fill the outer rectangle - -# Pattern properties -pattern_width, pattern_height = 5, 10 # Width and height of the small rectangles -cols = int(outer_rect_w / pattern_width) # Number of small rectangles horizontally -rows = int(outer_rect_h / pattern_height) # Number of small rectangles vertically - -# Set color for the pattern -pdf.set_fill_color(255, 255, 255) # White for the spacing - -# Create the pattern -for i in range(cols): - for j in range(rows): - if (i + j) % 2 == 0: # Check for alternate placement - x = outer_rect_x + i * pattern_width - y = outer_rect_y + j * pattern_height - pdf.rect(x, y, pattern_width, pattern_height, 'F') - -pdf.set_draw_color(0, 0, 0) # Black border -pdf.ellipse(outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h) - -# Output the PDF -pdf.output('pattern_filled_rectangle.pdf') \ No newline at end of file diff --git a/test/image/filled_rectangle.pdf b/filled_rectangle.pdf similarity index 100% rename from test/image/filled_rectangle.pdf rename to filled_rectangle.pdf diff --git a/pattern_filled_rectangle.pdf b/pattern_filled_rectangle.pdf deleted file mode 100644 index 3092d0072ff0ad579afee8a792176140b10b7420..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 981 zcmZWoTS!zv7)BooCR2it)?_@xHn%60L&Av$N~U?wRH6Z0QQV zXevYomJfvyK@voC#SDAWim-=@$O?QgiL%REFJc?fjINh-9?tOpbLRW!`@a9rZFIQ{ z4T1@npa@Av7qHt=b59II)To3oU|$_;6dKs67a%W=lZ39~I5e&&oJ6DSJPyq~E-eLE z3vd)3rqSHt2*o-??ubIM3#%l+!0WIUqMguaklCF$)v*!<-Q)A4hU}*>tMW|4(!O`I zdsM4q;!a6sS8-zQ?avQ|BbRE9^&Wn<@&YYp4Au_kgS+KN)PZ3s=r2osIZze#JLX#l z^KMV$gPAplE|yOWj9!-lrz&%vH~cuU+WTgqH7l4SJnYLJ5hky=@}|Gdlr1OE8-Mrp zpMIROFU)^kinhP30ymrd+WXHRJ7MnnSi({nt(d3vsl+z2QGH$(EYMDBBd3LDe zZ0g$h%-p^2a609)-*2n1eF|07@BOp%diD6n>|YmFl7APMll#e&s}Fo!lQhM&I$X_N zTE_vZ4F}@T&zxCO$MWAHrUKI zlUT5gioC7ZdOJE5szgYLcVvk5U%DYZF|0XMj=7;5a))UZ)Dn>hueGM@`aO_Jr8*ap^%HhhOk--63E@~awc)A=yZ*TMV3KsZl%W!{sCsD BHXr~1 From f5d460e7b25e9fcc2481901241c43ec160ec58dc Mon Sep 17 00:00:00 2001 From: Jamil Daoud Date: Tue, 5 Dec 2023 12:40:03 +0300 Subject: [PATCH 10/21] Developed a function that produces patterns of rectangles, squares, and circles in eitheran outer shape of a rectangle or a circle --- Working_function_rect_circ.py | 35 ++++++++++++++++++++++++++++++++++ pattern_filled_rectangle.pdf | Bin 0 -> 981 bytes 2 files changed, 35 insertions(+) create mode 100644 Working_function_rect_circ.py create mode 100644 pattern_filled_rectangle.pdf diff --git a/Working_function_rect_circ.py b/Working_function_rect_circ.py new file mode 100644 index 000000000..6e0ce3a18 --- /dev/null +++ b/Working_function_rect_circ.py @@ -0,0 +1,35 @@ +from fpdf import FPDF + +pdf = FPDF() + +# Add a page +pdf.add_page() + +# Set fill color (RGB) +pdf.set_fill_color(255, 205, 0) # Setting the color to yellow + +# Draw the outer rectangle +outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h = 10, 10, 50, 30 +pdf.ellipse(outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h, 'F') # Fill the outer rectangle + +# Pattern properties +pattern_width, pattern_height = 5, 10 # Width and height of the small rectangles +cols = int(outer_rect_w / pattern_width) # Number of small rectangles horizontally +rows = int(outer_rect_h / pattern_height) # Number of small rectangles vertically + +# Set color for the pattern +pdf.set_fill_color(255, 255, 255) # White for the spacing + +# Create the pattern +for i in range(cols): + for j in range(rows): + if (i + j) % 2 == 0: # Check for alternate placement + x = outer_rect_x + i * pattern_width + y = outer_rect_y + j * pattern_height + pdf.rect(x, y, pattern_width, pattern_height, 'F') + +pdf.set_draw_color(0, 0, 0) # Black border +pdf.ellipse(outer_rect_x, outer_rect_y, outer_rect_w, outer_rect_h) + +# Output the PDF +pdf.output('pattern_filled_rectangle.pdf') \ No newline at end of file diff --git a/pattern_filled_rectangle.pdf b/pattern_filled_rectangle.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9f8badba38f4210ec286d3ebb12c2dc25fccf51c GIT binary patch literal 981 zcmZWoTS!zv7)BooCR2im_)3#s4pc^bj)m5t zoZB<_V0!hTi)E98W7lQ>sfw)U^*>Im_Ptqb%?M-(5BoDmg{dp9oSAR4rOUnNrQiJn zrynQniwj>9k@lCB;AW#wfB(7hM*H~DA~P6haf}u{ni^Mzv--ev+O1cKmg#es=Z1^V zCa+D*&fohEXOd0!`)%d6Pr>rKy?+v~SC4ca_wUkj?|$;+>Vqb(Ns3}h9j@js ztz!Vyg#0n+<4$;C8$eDH=h6dIhy5Y7oODB?xxeYyT zUO*Hqf&@D$jTRyl?FmHv0U=08Fudlsppgj5V}zK`G(>b4>jaqVDwIr;S(Hq&D4A`d zl(&tFvaQ&9J33XWhDnfjWRUe=sv$j5tUEN0xuF|!hiE0#7LLs+E;2;^>fIg=Pw4Z6m|q9`CcyTaoJ{{UTn BHW>f_ literal 0 HcmV?d00001 From 6ed056397c8330b1fb0c229aaa7dc1ec3fda64e8 Mon Sep 17 00:00:00 2001 From: hmkhalif Date: Tue, 5 Dec 2023 15:35:46 +0300 Subject: [PATCH 11/21] editing set fill pattern to user input and creating PDFPattern object --- fpdf/fpdf.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index 2be725974..6c5977be0 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -106,6 +106,7 @@ class Image: PDFPage, ZOOM_CONFIGS, stream_content_for_raster_image, + PDFPattern ) from .recorder import FPDFRecorder from .sign import Signature @@ -1021,7 +1022,7 @@ def set_fill_color(self, r, g=-1, b=-1): if self.page > 0: self._out(self.fill_color.serialize().lower()) - def set_fill_pattern(self): + def set_fill_pattern(self, bbox, x_step, y_step, pattern_type, paint_type=None, tiling_type=1, resources=None, matrix=None): """ Defines the pattern used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or grey scale. @@ -1033,11 +1034,20 @@ def set_fill_pattern(self): g (int): green component (between 0 and 255) b (int): blue component (between 0 and 255) """ - print("Hello") - print(self.fill_pattern) - if self.page > 0: - print(self.fill_pattern.serialize().lower()) - self._out(self.fill_pattern.serialize()) + #print("Hello") + pattern = PDFPattern( + pattern_type= pattern_type, # Assuming tiling pattern is always used + paint_type=paint_type, + tiling_type=tiling_type, + bbox=bbox, + x_step=x_step, + y_step=y_step, + resources=resources, + matrix=matrix + ) + + + def set_text_color(self, r, g=-1, b=-1): """ From 5ead1a49db9780e5d75160d63d387341ecd5400b Mon Sep 17 00:00:00 2001 From: hmkhalif Date: Tue, 5 Dec 2023 15:36:49 +0300 Subject: [PATCH 12/21] adding pattern to dictionary of patterns --- fpdf/fpdf.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index 6c5977be0..cd821e870 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -1046,7 +1046,13 @@ def set_fill_pattern(self, bbox, x_step, y_step, pattern_type, paint_type=None, matrix=matrix ) - + # Add the pattern to a patterns dictionary in the PDF document + pattern_id = len(self.patterns) + 1 + self.patterns[pattern_id] = pattern + #print(self.patterns) + # Set this pattern as the current fill pattern + self.current_fill_pattern = pattern_id + #print(self.current_fill_pattern) def set_text_color(self, r, g=-1, b=-1): From cf020d13df37c21fce97f2d0fba22aebbf176ac4 Mon Sep 17 00:00:00 2001 From: hmkhalif Date: Tue, 5 Dec 2023 15:39:31 +0300 Subject: [PATCH 13/21] adding apply pattern function that draws pattern --- fpdf/fpdf.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index cd821e870..ff461fff5 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -1375,6 +1375,37 @@ def dashed_line(self, x1, y1, x2, y2, dash_length=1, space_length=1): self.line(x1, y1, x2, y2) self.set_dash_pattern() + def apply_fill_pattern(self, pattern_id, x, y, w, h): + pattern = self.patterns.get(pattern_id) + if pattern: + + # Use the pattern's bbox to determine the size of each tile + pattern_width, pattern_height = pattern.bbox[2], pattern.bbox[3] + + # Use the pattern's x_step and y_step for spacing + x_step, y_step = pattern.x_step, pattern.y_step + + # Calculate how many times the pattern will repeat + x_repeat = int(w / x_step) + y_repeat = int(h / y_step) + + # Loop through and draw the pattern + for i in range(x_repeat): + for j in range(y_repeat): + # Calculate the top-left corner of the current pattern tile + pattern_x = x + i * x_step + pattern_y = y + j * y_step + if pattern.pattern_type == "circles": + if pattern.paint_type is not None: + self.set_fill_color(*pattern.paint_type) + self.ellipse(pattern_x, pattern_y, pattern_width, pattern_height, 'F') + self.ellipse(pattern_x, pattern_y, pattern_width, pattern_height, 'D') + if pattern.pattern_type == "squares": + if pattern.paint_type is not None: + self.set_fill_color(*pattern.paint_type) + self.rect(pattern_x, pattern_y, pattern_width, pattern_height, 'F') + self.rect(pattern_x, pattern_y, pattern_width, pattern_height, 'D') + @check_page def rect(self, x, y, w, h, style=None, round_corners=False, corner_radius=0): """ From bd5a778e813eeaa4c878960f8b651b11f28c141c Mon Sep 17 00:00:00 2001 From: hmkhalif Date: Tue, 5 Dec 2023 15:40:01 +0300 Subject: [PATCH 14/21] adding error message when applying pattern --- fpdf/fpdf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index ff461fff5..ff343e32b 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -1405,7 +1405,9 @@ def apply_fill_pattern(self, pattern_id, x, y, w, h): self.set_fill_color(*pattern.paint_type) self.rect(pattern_x, pattern_y, pattern_width, pattern_height, 'F') self.rect(pattern_x, pattern_y, pattern_width, pattern_height, 'D') - + else: + raise ValueError('Not defined pattern type') + @check_page def rect(self, x, y, w, h, style=None, round_corners=False, corner_radius=0): """ From d09c5946ad1ab11099b75b4abe9c95606f98aca8 Mon Sep 17 00:00:00 2001 From: hmkhalif Date: Tue, 5 Dec 2023 15:40:34 +0300 Subject: [PATCH 15/21] editing apply function to fix loop syntax and prevent errors --- fpdf/fpdf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index ff343e32b..ae1d49237 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -1400,7 +1400,7 @@ def apply_fill_pattern(self, pattern_id, x, y, w, h): self.set_fill_color(*pattern.paint_type) self.ellipse(pattern_x, pattern_y, pattern_width, pattern_height, 'F') self.ellipse(pattern_x, pattern_y, pattern_width, pattern_height, 'D') - if pattern.pattern_type == "squares": + elif pattern.pattern_type == "squares": if pattern.paint_type is not None: self.set_fill_color(*pattern.paint_type) self.rect(pattern_x, pattern_y, pattern_width, pattern_height, 'F') From c1fff08ce3152d33124b813186f3f4dcc601efc7 Mon Sep 17 00:00:00 2001 From: hmkhalif Date: Tue, 5 Dec 2023 15:48:49 +0300 Subject: [PATCH 16/21] adding trial file with pdf result with patterns after these changes --- trial.ipynb | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++ trying.pdf | Bin 0 -> 11473 bytes 2 files changed, 149 insertions(+) create mode 100644 trial.ipynb create mode 100644 trying.pdf diff --git a/trial.ipynb b/trial.ipynb new file mode 100644 index 000000000..246281888 --- /dev/null +++ b/trial.ipynb @@ -0,0 +1,149 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 11, + "id": "2ea6ad7a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{1: }\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "DeviceRGB(r=0.09019607843137255, g=0.25882352941176473, b=0.796078431372549, a=None)\n", + "0.0902 0.2588 0.7961 rg\n", + "{1: , 2: }\n", + "{1: , 2: , 3: }\n" + ] + }, + { + "ename": "ValueError", + "evalue": "Not defined pattern type", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[11], line 16\u001b[0m\n\u001b[1;32m 13\u001b[0m pdf\u001b[38;5;241m.\u001b[39mrect(\u001b[38;5;241m100\u001b[39m,\u001b[38;5;241m100\u001b[39m,\u001b[38;5;241m50\u001b[39m,\u001b[38;5;241m50\u001b[39m,\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPATTERN\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 15\u001b[0m pdf\u001b[38;5;241m.\u001b[39mset_fill_pattern([\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m5\u001b[39m,\u001b[38;5;241m5\u001b[39m],\u001b[38;5;241m10\u001b[39m, \u001b[38;5;241m10\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m---> 16\u001b[0m pdf\u001b[38;5;241m.\u001b[39mrect(\u001b[38;5;241m50\u001b[39m,\u001b[38;5;241m50\u001b[39m,\u001b[38;5;241m50\u001b[39m,\u001b[38;5;241m50\u001b[39m,\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPATTERN\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 18\u001b[0m pdf\u001b[38;5;241m.\u001b[39moutput(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtrying.pdf\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m~/Desktop/p5/fpdf2-b/fpdf/fpdf.py:202\u001b[0m, in \u001b[0;36mcheck_page..wrapper\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 200\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpage \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdry_run\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;129;01mor\u001b[39;00m kwargs\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msplit_only\u001b[39m\u001b[38;5;124m\"\u001b[39m)):\n\u001b[1;32m 201\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m FPDFException(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNo page open, you need to call add_page() first\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 202\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m fn(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[0;32m~/Desktop/p5/fpdf2-b/fpdf/fpdf.py:1450\u001b[0m, in \u001b[0;36mFPDF.rect\u001b[0;34m(self, x, y, w, h, style, round_corners, corner_radius)\u001b[0m\n\u001b[1;32m 1447\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m style \u001b[38;5;241m==\u001b[39m RenderStyle\u001b[38;5;241m.\u001b[39mP:\n\u001b[1;32m 1448\u001b[0m \u001b[38;5;66;03m# Check if a current pattern is set and apply it\u001b[39;00m\n\u001b[1;32m 1449\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcurrent_fill_pattern \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m-> 1450\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mapply_fill_pattern(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcurrent_fill_pattern, x, y, w, h)\n\u001b[1;32m 1451\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \n\u001b[1;32m 1453\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m round_corners \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n", + "File \u001b[0;32m~/Desktop/p5/fpdf2-b/fpdf/fpdf.py:1412\u001b[0m, in \u001b[0;36mFPDF.apply_fill_pattern\u001b[0;34m(self, pattern_id, x, y, w, h)\u001b[0m\n\u001b[1;32m 1410\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrect(pattern_x, pattern_y, pattern_width, pattern_height, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mD\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 1411\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1412\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNot defined pattern type\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mValueError\u001b[0m: Not defined pattern type" + ] + } + ], + "source": [ + "from fpdf import FPDF\n", + "pdf = FPDF()\n", + "pdf.compress= False\n", + "pdf.add_page()\n", + "\n", + "#color is optional \n", + "pdf.set_fill_pattern([0,0,5,5],10, 10,\"circles\", (23,66,203))\n", + "pdf.rect(10,10,50,50,\"PATTERN\")\n", + "\n", + "pdf.set_fill_pattern([0,0,5,5],10, 10,\"squares\")\n", + "pdf.rect(100,100,50,50,\"PATTERN\")\n", + "\n", + "#should get error if not circle or square\n", + "#pdf.set_fill_pattern([0,0,5,5],10, 10, \"s\")\n", + "#pdf.rect(50,50,50,50,\"PATTERN\")\n", + "\n", + "pdf.output(\"trying.pdf\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd625700", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0e1098a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "707dd1fe", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/trying.pdf b/trying.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1c9083c18773ee8127ad24e9ad033557da41b196 GIT binary patch literal 11473 zcmdU#PjA~s5XJBO6nhEM9!hcfpG6QLv12rCiUdhc4RTNw+I3+|fh?m*KYfS$-djoy z7+%d>oX643&d#&+BjtVc=KSI(pB9OCncMyOck<*(vO3${Zx7BVtKY6a-MJ5ih2DNl zR=@Y3uGi0ZU)+bxu2fx>=B;Z>pSGPv-+%qwyVaZZRezT}eVX*!PeZxa(f8E_5-0JnVKil2h-)?dF&JFFo)gou>!}?}-b+pXT z;@JK6&~FcSu0+n8_1>f^yzTFH_xnwM=c?n9!{SHvhE&yi)o-s3e>tBuxgTC~ci8vq zTie;MNtRZP`^SD{U1mE?^Qvv_N7L2b?XQwDPpjOuS)G=(yLFU4ON+)8U0PJG^+j5h zuBg(okk}-J4|#~?EnXP1C{S^eNZLA9BxE(66}IxBB8629t5K@0kR=g%+_=jnHvMkK zfu?Cw@1p}vo2O-ZZ6yaFq63f|Ipn5!`!M85b#%^kW-c3?(1=_NrNX*qB*$4P75lMV^D?)4%t_I0IKw^nV;*$%}fd}36tOJ4?_XehNCicN@B<8#zq63heGO{E{ zVoETT4uH0-C=zouNcMp&HHC`yJaBR$I`E*Io^v2V4SOR~ITO&9^Ad?UOGr$aSrQ~M zB}j}c(iRmXiLn|b`#_eOLdEF7qMDv|z#dO?Ka!XdB(^)EtQ35^JoQJ<#BCe$Kw_go zcwrzhg-9$Jn2IdY78N6jv6^CRD`cJYINS@JT)1^hXnM|pNMdY;P~%KMTh0q&lW>-h zm@=~{L}JN6VrGH1tSAz5HO7Jid?sd7tQZ|wRMWE#h{W71pvIZl=ZKM*^MZ&DKyu2+ zq7aEC1BvMXXv>NsF;`;@4uHgLiWNr(melmD10pdu3#f4>pe^Sm5_6W2oHDW`NMcGb zm06%ID~iNijWIZYEHxELd~!jbLd}D2dd`6eHSCQ{SV<`bS>cCcJ61%J$naovVlpP}Tq~8I{>KH5CI_ahCVAh++JMN6U)s*a4 z+`hWj452oOCd??jQ6`m8O>anDWdg{mD_Uz+MT0lWgg5N>$eYFPVBQ;%P~L#Vni3$b z8H(VVFr##XnN)(fyaA7u2~?}DIIdL{g*VKkHzUf`@ltm%?~TB&odS}Y67a1VitU;( zqjZCrQpCHw0jZSR=H_W6r==b=2v(z2TdJ~aPZ-`G#31HU@MSV?}QMjQ@ zDT1Hgkm1ZE-dQ)YpR2}b@J5;NhW#FSv)CPc$D7LjT5$AO?x{)ADo>mEEbhxTZSBw6 zHg@}~v+<@ZLoT$p^8n$sxEG*`_X5%&IxE#_YH~8OwyipU10-Ug-!5d}58!=nni0H@^?NN8U7r?5DvLk$dKqpjpc=lAs;jY7; zJ*C56_5Fk2!8oABkpblg6f z?92Rbuh z$M|G_j8FE5_;i1aPxfbDyxDi$)BQ0%*&pMR{UJWxALCQ~4M$jc){}=>hZCbZ75Zks z+q~-!?!(GX(7M(8{)-)3eR*rgNT2iP8GpX~cyzF|J}Pl$=SYXsu;=ST?|wM{InVOK z9#ATKC@HJ%51&6S%f~++C4brXmr3TDB#ZxCT~&6D^wN#jIv1jDJ6`K-+2P;OHQ#;v zy1e=SHSe>^&eopfdT&jR*ADyj^-aGI2Z!HX|Jz%8tGBz|!3{@$?a1!S?d8r5+aCUZ z?mj#@f7U)fzj)rBy(qJ@ygIXUwJ*Ah7rrYx-<)?BPv>6|CVF>R?+;-l)=}$|M~_~- HzDWK9`5xH} literal 0 HcmV?d00001 From 04a42ddc993d6e54be81a946a73f563d0d7125ee Mon Sep 17 00:00:00 2001 From: smubarak7 Date: Tue, 5 Dec 2023 17:52:28 +0300 Subject: [PATCH 17/21] removing print statement after testing code works --- fpdf/fpdf.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index ae1d49237..d568ae586 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -1054,6 +1054,11 @@ def set_fill_pattern(self, bbox, x_step, y_step, pattern_type, paint_type=None, self.current_fill_pattern = pattern_id #print(self.current_fill_pattern) + def set_current_pattern(self, pattern_id): + if pattern_id in self.patterns: + self.current_fill_pattern = pattern_id + else: + raise ValueError(f"Pattern ID '{pattern_id}' not found in patterns.") def set_text_color(self, r, g=-1, b=-1): """ From 79641f9e71475f4425d9ea34be55e091e3c5b786 Mon Sep 17 00:00:00 2001 From: smubarak7 Date: Tue, 5 Dec 2023 17:56:28 +0300 Subject: [PATCH 18/21] finalized the set current pattern that updates patterns --- fpdf/fpdf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index d568ae586..c26117045 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -1055,9 +1055,13 @@ def set_fill_pattern(self, bbox, x_step, y_step, pattern_type, paint_type=None, #print(self.current_fill_pattern) def set_current_pattern(self, pattern_id): + if pattern_id in self.patterns: + self.current_fill_pattern = pattern_id + else: + raise ValueError(f"Pattern ID '{pattern_id}' not found in patterns.") def set_text_color(self, r, g=-1, b=-1): From fae1428ab1c34d306cb3b373a784185cca6300e1 Mon Sep 17 00:00:00 2001 From: smubarak7 Date: Tue, 5 Dec 2023 17:58:21 +0300 Subject: [PATCH 19/21] modifying RenderStyle so shapes can have pattern style --- fpdf/enums.py | 73 +++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/fpdf/enums.py b/fpdf/enums.py index f998a796c..0b25fa64d 100644 --- a/fpdf/enums.py +++ b/fpdf/enums.py @@ -326,44 +326,43 @@ def should_fill_cell(self, i, j): raise NotImplementedError -class RenderStyle(CoerciveEnum): - "Defines how to render shapes" - - D = intern("DRAW") - """ - Draw lines. - Line color can be controlled with `fpdf.fpdf.FPDF.set_draw_color()`. - Line thickness can be controlled with `fpdf.fpdf.FPDF.set_line_width()`. - """ - - F = intern("FILL") - """ - Fill areas. - Filling color can be controlled with `fpdf.fpdf.FPDF.set_fill_color()`. - """ - - DF = intern("DRAW_FILL") - "Draw lines and fill areas" - - @property - def operator(self): - return {self.D: "S", self.F: "f", self.DF: "B"}[self] - - @property - def is_draw(self): - return self in (self.D, self.DF) - - @property - def is_fill(self): - return self in (self.F, self.DF) - @classmethod - def coerce(cls, value): - if not value: - return cls.D - if value == "FD": - value = "DF" - return super(cls, cls).coerce(value) +class RenderStyle(CoerciveEnum): + "Defines how to render shapes" +D = intern("DRAW") +""" +Draw lines. +Line color can be controlled with `fpdf.fpdf.FPDF.set_draw_color()`. +Line thickness can be controlled with `fpdf.fpdf.FPDF.set_line_width()`. +""" +F = intern("FILL") +""" +Fill areas. +Filling color can be controlled with `fpdf.fpdf.FPDF.set_fill_color()`. +""" +DF = intern("DRAW_FILL") +"Draw lines and fill areas" +# adding pattern +P = intern("PATTERN") +@property +def operator(self): + return {self.D: "S", self.F: "f", self.DF: "B", self.P: "f"}[self] + +@property + def is_draw(self): + return self in (self.D, self.DF, self.P) # Include pattern in drawing + @property + def is_fill(self): + return self in (self.F, self.DF, self.P) + @classmethod + def coerce(cls, value): + if not value: + return cls.D + if value == "FD": + value = "DF" +return super(cls, cls).coerce(value) + + class TextMode(CoerciveIntEnum): From 4e6bbc927ee5d207335eabc667c209af3646c058 Mon Sep 17 00:00:00 2001 From: smubarak7 Date: Tue, 5 Dec 2023 18:01:38 +0300 Subject: [PATCH 20/21] editing rectangle shape to allow for pattern style --- fpdf/fpdf.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index c26117045..3542209a0 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -1061,7 +1061,7 @@ def set_current_pattern(self, pattern_id): self.current_fill_pattern = pattern_id else: - + raise ValueError(f"Pattern ID '{pattern_id}' not found in patterns.") def set_text_color(self, r, g=-1, b=-1): @@ -1448,6 +1448,16 @@ def rect(self, x, y, w, h, style=None, round_corners=False, corner_radius=0): """ style = RenderStyle.coerce(style) + + +print("these are the patterns", self.patterns) +print("current pattern,", self.current_fill_pattern) + if style == RenderStyle.P: + # Check if a current pattern is set and apply it + if self.current_fill_pattern is not None: + self.apply_fill_pattern(self.current_fill_pattern, x, y, w, h) + return None + if round_corners is not False: self._draw_rounded_rect(x, y, w, h, style, round_corners, corner_radius) else: From 1e7ab4d530a1ddef061d9e6ee9fbc0605c9ad390 Mon Sep 17 00:00:00 2001 From: smubarak7 Date: Tue, 5 Dec 2023 18:10:00 +0300 Subject: [PATCH 21/21] removing print statement after testing --- fpdf/fpdf.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index 3542209a0..8bc70b89e 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -1446,18 +1446,19 @@ def rect(self, x, y, w, h, style=None, round_corners=False, corner_radius=0): corner_radius: Optional radius of the corners """ - + style = RenderStyle.coerce(style) + + if style == RenderStyle.P: -print("these are the patterns", self.patterns) -print("current pattern,", self.current_fill_pattern) - if style == RenderStyle.P: # Check if a current pattern is set and apply it if self.current_fill_pattern is not None: + self.apply_fill_pattern(self.current_fill_pattern, x, y, w, h) - return None + return None + if round_corners is not False: self._draw_rounded_rect(x, y, w, h, style, round_corners, corner_radius) else: