diff --git a/include/wx/pdfdocdef.h b/include/wx/pdfdocdef.h index e4b78f7c..b95304bb 100644 --- a/include/wx/pdfdocdef.h +++ b/include/wx/pdfdocdef.h @@ -69,7 +69,7 @@ Or you can send a mail to the author \section version Version history
-
1.0.0 - December 2020 (planned)
+
1.0.0 - September 2021
wxPdfDocument is compatible with wxWidgets versions 3.0.x and 3.1.x. @@ -79,11 +79,15 @@ General changes:
- Added transformation matrix support for wxPdfDC - Added attribute "char-spacing" for XML markup element "span" - Added maximum height attribute for table rows in XML markup +- Implemented extended support for fill patterns (template based patterns, various hatch patterns) +- Enhanced support for wxBrush styles in wxPdfDC (stipple and hatch styles) - Changed data type of image measures in XML markup (from integer to double) - Optimized wxPdfDC output (setting of pens, brushes, state changes) Fixed bugs:
- Fixed issue with bitmap images in wxPdfDC (now using globally unique identifiers) +- Fixed wxPdfDC issue with pen and brush color +- Fixed issue with patterns in templates - Use the transparent background mode by default (relevant for alpha support in wxPdfDC)
diff --git a/include/wx/pdfdocument.h b/include/wx/pdfdocument.h index 7d905636..af30e07c 100644 --- a/include/wx/pdfdocument.h +++ b/include/wx/pdfdocument.h @@ -515,13 +515,35 @@ class WXDLLIMPEXP_PDFDOC wxPdfDocument /// Add an image pattern /** - * Add a pattern which can be reference in draw or fill pattern methods + * Add an image pattern which can be referenced in draw or fill pattern methods * \param patternName the name of the pattern (case sensitive) - * \param image the image to use for the pattern + * \param image the image to be used as a pattern + * \param width the display width of the pattern + * \param height the display height of the pattern + */ + virtual bool AddPattern(const wxString& patternName, const wxImage& image, double width, double height); + + /// Add a template based pattern + /** + * Add a template based pattern which can be referenced in draw or fill pattern methods + * \param patternName the name of the pattern (case sensitive) + * \param templateId the id of the template to be used as a pattern + * \param width the display width of the pattern + * \param height the display height of the pattern + */ + virtual bool AddPattern(const wxString& patternName, int templateId, double width, double height); + + /// Add a hatched pattern + /** + * Add a hatched pattern which can be referenced in draw or fill pattern methods + * \param patternName the name of the pattern (case sensitive) + * \param patternStyle the pattern style to be used as a pattern * \param width the display width * \param height the display height + * \param drawColour the foreground colour used for hatching + * \param fillColour the background colour to fill the pattern background (optional) */ - virtual bool AddPattern(const wxString& patternName, const wxImage& image, double width, double height); + virtual bool AddPattern(const wxString& patternName, wxPdfPatternStyle patternStyle, double width, double height, const wxColour& drawColour, const wxColour& fillColour = wxColour()); /// Defines the colour used for all drawing operations. /** @@ -2649,6 +2671,9 @@ class WXDLLIMPEXP_PDFDOC wxPdfDocument /// Add spot colours virtual void PutSpotColours(); + /// Initialize object ids of patterns + virtual void InitPatternIds(); + /// Add patterns virtual void PutPatterns(); diff --git a/include/wx/pdfpattern.h b/include/wx/pdfpattern.h index 49d18474..3bfe668f 100644 --- a/include/wx/pdfpattern.h +++ b/include/wx/pdfpattern.h @@ -17,6 +17,7 @@ // wxPdfDocument headers #include "wx/pdfdocdef.h" +#include "wx/pdfproperties.h" class WXDLLIMPEXP_FWD_PDFDOC wxPdfImage; @@ -32,6 +33,25 @@ class WXDLLIMPEXP_PDFDOC wxPdfPattern */ wxPdfPattern(int index, double width, double height); + /// Constructor for pattern + /** + * \param index The pattern index + * \param width The pattern width + * \param height The pattern height + * \param templateId The id of the template to be used as a pattern + */ + wxPdfPattern(int index, double width, double height, int templateId); + + /// Constructor for pattern + /** + * \param index The pattern index + * \param width The pattern width + * \param height The pattern height + * \param drawColour The foreground colour to be used for hatching + * \param fillColour The background colour to be used to fill the pattern background + */ + wxPdfPattern(int index, double width, double height, wxPdfPatternStyle patternStyle, const wxColour& drawColour, const wxColour& fillColour = wxColour()); + /// Copy constructor wxPdfPattern(const wxPdfPattern& pattern); @@ -56,11 +76,34 @@ class WXDLLIMPEXP_PDFDOC wxPdfPattern /// Get pattern height double GetHeight() const {return m_height; }; + /// Get template id + int GetTemplateId() const { return m_templateId; } + + /// Get pattern style + wxPdfPatternStyle GetPatternStyle() const { return m_patternStyle; } + + /// Get draw color + wxColour GetDrawColour() const { return m_drawColour; } + + /// Set fill color + void SetFillColour(const wxColour& fillColour) { m_fillColour = fillColour; m_hasFillColour = true; } + + /// Get fill color + wxColour GetFillColour() const { return m_fillColour; } + + /// Check whether fill color is set + bool HasFillColour() const { return m_hasFillColour; } + private: int m_objIndex; ///< object index int m_index; ///< pattern index + wxPdfPatternStyle m_patternStyle; ///< pattern style wxPdfImage* m_image; ///< image + int m_templateId; ///< template id + wxColour m_drawColour; ///< foregorund colour + wxColour m_fillColour; ///< background colour + bool m_hasFillColour; ///< flag whether background colour is defined for the pattern double m_width; ///< pattern width double m_height; ///< pattern height @@ -70,32 +113,4 @@ class WXDLLIMPEXP_PDFDOC wxPdfPattern double m_matrix[6]; ///< transformation matrix }; -#if 0 -Pattern dictionary Type 1 -------------------------- - -/Type /Pattern -/PatternType 1 - tiling pattern -/PaintType 1 - colored - 2 - uncolored -/TilingType 1 - constant spacing - 2 - no distortion - 3 - constant spacing faster tiling -/BBox [ left bottom right top ] -/XStep - horizontal spacing != 0 -/YStep - vertical spacing != 0 -/Resources -/Matrix [1 0 0 1 0 0] - -Pattern dictionary Type 2 -------------------------- - -/Type /Pattern -/PatternType 2 - shading pattern -/Shading dictionary or stream -/Matrix [1 0 0 1 0 0] -/ExtGState dictionary - -#endif - #endif diff --git a/include/wx/pdfproperties.h b/include/wx/pdfproperties.h index ad3701d9..b0d8ff23 100644 --- a/include/wx/pdfproperties.h +++ b/include/wx/pdfproperties.h @@ -175,6 +175,26 @@ enum wxPdfMarker wxPDF_MARKER_LAST // Marks the last available marker symbol; do not use! }; +/// Pattern styles +enum wxPdfPatternStyle +{ + wxPDF_PATTERNSTYLE_NONE, + wxPDF_PATTERNSTYLE_IMAGE, + wxPDF_PATTERNSTYLE_TEMPLATE, + // Hatch styles + wxPDF_PATTERNSTYLE_FIRST_HATCH, + wxPDF_PATTERNSTYLE_BDIAGONAL_HATCH = wxPDF_PATTERNSTYLE_FIRST_HATCH, + wxPDF_PATTERNSTYLE_CROSSDIAG_HATCH, + wxPDF_PATTERNSTYLE_FDIAGONAL_HATCH, + wxPDF_PATTERNSTYLE_CROSS_HATCH, + wxPDF_PATTERNSTYLE_HORIZONTAL_HATCH, + wxPDF_PATTERNSTYLE_VERTICAL_HATCH, + wxPDF_PATTERNSTYLE_HERRINGBONE_HATCH, + wxPDF_PATTERNSTYLE_BASKETWEAVE_HATCH, + wxPDF_PATTERNSTYLE_BRICK_HATCH, + wxPDF_PATTERNSTYLE_LAST_HATCH = wxPDF_PATTERNSTYLE_BRICK_HATCH +}; + /// Linear gradient types enum wxPdfLinearGradientType { diff --git a/samples/minimal/drawing.cpp b/samples/minimal/drawing.cpp index a7908973..aa8af950 100644 --- a/samples/minimal/drawing.cpp +++ b/samples/minimal/drawing.cpp @@ -207,6 +207,78 @@ drawing(bool testMode) pdf.SetFillColour(wxColour(200, 200, 200)); pdf.RoundedRect(140, 255, 40, 30, 8.0, wxPDF_CORNER_TOP_RIGHT | wxPDF_CORNER_BOTTOM_RIGHT, wxPDF_STYLE_FILLDRAW); + // Examples of various fill patterns + pdf.AddPage(); + + pdf.Text(10, 15, wxS("Fill pattern examples")); + pdf.SetDrawColour(wxColour(0, 0, 0)); + + int tplHatch = pdf.BeginTemplate(0, 0, 4, 4); + pdf.SetTextColour(0); + pdf.SetDrawColour(wxColour(0, 0, 0)); + pdf.SetFillColour(wxColour(128, 128, 255)); + pdf.Circle(2, 2, 1.5, 0, 360, wxPDF_STYLE_FILLDRAW); + pdf.SetFillColour(wxColour(128, 255, 128)); + pdf.Rect(2, 2, 1.75, 1.75, wxPDF_STYLE_FILLDRAW); + pdf.EndTemplate(); + + pdf.AddPattern(wxS("hatch1"), wxPDF_PATTERNSTYLE_BDIAGONAL_HATCH, 1, 1, wxColour(224, 0, 0)); + pdf.AddPattern(wxS("hatch2"), wxPDF_PATTERNSTYLE_FDIAGONAL_HATCH, 2, 2, wxColour(160, 160, 0)); + pdf.AddPattern(wxS("hatch3"), wxPDF_PATTERNSTYLE_CROSSDIAG_HATCH, 4, 4, wxColour(224, 0, 224)); + pdf.AddPattern(wxS("hatch4"), wxPDF_PATTERNSTYLE_HORIZONTAL_HATCH, 1, 1, wxColour(255, 0, 0)); + pdf.AddPattern(wxS("hatch5"), wxPDF_PATTERNSTYLE_VERTICAL_HATCH, 2, 2, wxColour(0, 0, 255)); + pdf.AddPattern(wxS("hatch6"), wxPDF_PATTERNSTYLE_CROSS_HATCH, 4, 4, wxColour(0, 96, 0)); + pdf.AddPattern(wxS("hatch7"), wxPDF_PATTERNSTYLE_BRICK_HATCH, 2, 2, wxColour(96, 96, 96), wxColour(255, 192, 128)); + pdf.AddPattern(wxS("hatch8"), wxPDF_PATTERNSTYLE_HERRINGBONE_HATCH, 2, 2, wxColour(128, 128, 128)); + pdf.AddPattern(wxS("hatch9"), wxPDF_PATTERNSTYLE_BASKETWEAVE_HATCH, 2, 2, wxColour(224, 160, 96)); + + pdf.AddPattern(wxS("hatch10"), tplHatch, 4, 4); + pdf.AddPattern(wxS("hatch11"), tplHatch, 6, 6); + + pdf.Text(25, 25, wxS("BDiagonal")); + pdf.SetFillPattern(wxS("hatch1")); + pdf.Rect(25, 30, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(75, 25, wxS("FDiagonal")); + pdf.SetFillPattern(wxS("hatch2")); + pdf.Rect(75, 30, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(125, 25, wxS("CrossDiag")); + pdf.SetFillPattern(wxS("hatch3")); + pdf.Rect(125, 30, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(25, 65, wxS("Horizontal")); + pdf.SetFillPattern(wxS("hatch4")); + pdf.Rect(25, 70, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(75, 65, wxS("Vertical")); + pdf.SetFillPattern(wxS("hatch5")); + pdf.Rect(75, 70, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(125, 65, wxS("Cross")); + pdf.SetFillPattern(wxS("hatch6")); + pdf.Rect(125, 70, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(25, 105, wxS("Brick")); + pdf.SetFillPattern(wxS("hatch7")); + pdf.Rect(25, 110, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(75, 105, wxS("HerringBone")); + pdf.SetFillPattern(wxS("hatch8")); + pdf.Rect(75, 110, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(125, 105, wxS("BasketWeave")); + pdf.SetFillPattern(wxS("hatch9")); + pdf.Rect(125, 110, 25, 25, wxPDF_STYLE_FILLDRAW); + + pdf.Text(25, 145, wxS("Template 1x")); + pdf.SetFillPattern(wxS("hatch10")); + pdf.Rect(25, 150, 40, 40, wxPDF_STYLE_FILLDRAW); + + pdf.Text(75, 145, wxS("Template 2x")); + pdf.SetFillPattern(wxS("hatch11")); + pdf.Rect(75, 150, 40, 40, wxPDF_STYLE_FILLDRAW); + pdf.AddPage(); pdf.SetFont(wxS("Helvetica"), wxS("B"), 20); @@ -275,6 +347,7 @@ drawing(bool testMode) pdf.SetTextColour(0); pdf.AddPage(); + pdf.SetAutoPageBreak(false); pdf.SetFont(wxS("Helvetica"), wxS(""), 10); pdf.SetLineWidth(0.2); pdf.SetDrawColour(0); diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp index f992fb32..d4ac92b4 100644 --- a/samples/minimal/minimal.cpp +++ b/samples/minimal/minimal.cpp @@ -151,17 +151,10 @@ class PdfDocTutorial : public wxAppConsole static const wxCmdLineEntryDesc cmdLineDesc[] = { -#if wxCHECK_VERSION(2,9,0) { wxCMD_LINE_OPTION, "s", "sampledir", "wxPdfDocument samples directory", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_OPTION, "f", "fontdir", "wxPdfDocument font directory", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_SWITCH, "t", "testmode", "Non-interactive testmode", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_SWITCH, "h", "help", "Display help", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, -#else - { wxCMD_LINE_OPTION, wxS("s"), wxS("sampledir"), wxS("wxPdfDocument samples directory"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, - { wxCMD_LINE_OPTION, wxS("f"), wxS("fontdir"), wxS("wxPdfDocument font directory"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, - { wxCMD_LINE_SWITCH, wxS("t"), wxS("testmode"), wxS("Non-interactive testmode"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL }, - { wxCMD_LINE_SWITCH, wxS("h"), wxS("help"), wxS("Display help"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, -#endif { wxCMD_LINE_NONE } }; diff --git a/samples/pdfdc/printing.cpp b/samples/pdfdc/printing.cpp index f01a4158..1a2b0751 100644 --- a/samples/pdfdc/printing.cpp +++ b/samples/pdfdc/printing.cpp @@ -73,10 +73,6 @@ #include "printing.h" -#if !wxCHECK_VERSION(2, 9, 0) - #define wxPENSTYLE_DOT_DASH wxDOT_DASH -#endif - #ifndef __WXMSW__ #include "mondrian.xpm" #endif @@ -103,22 +99,16 @@ wxPageSetupDialogData* g_pageSetupData = (wxPageSetupDialogData*) NULL; IMPLEMENT_APP(MyApp) // Writes a header on a page. Margin units are in millimetres. -bool WritePageHeader(wxPrintout *printout, wxDC *dc, const wxChar *text, float mmToLogical); +bool WritePageHeader(wxPrintout* printout, wxDC* dc, const wxStringCharType* text, float mmToLogical); // The `main program' equivalent, creating the windows and returning the // main frame static const wxCmdLineEntryDesc cmdLineDesc[] = { -#if wxCHECK_VERSION(2,9,0) { wxCMD_LINE_OPTION, "s", "sampledir", "wxPdfDocument samples directory", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_OPTION, "f", "fontdir", "wxPdfDocument font directory", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_SWITCH, "h", "help", "Display help", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, -#else - { wxCMD_LINE_OPTION, wxS("s"), wxS("sampledir"), wxS("wxPdfDocument samples directory"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, - { wxCMD_LINE_OPTION, wxS("f"), wxS("fontdir"), wxS("wxPdfDocument font directory"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, - { wxCMD_LINE_SWITCH, wxS("h"), wxS("help"), wxS("Display help"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, -#endif { wxCMD_LINE_NONE } }; @@ -183,11 +173,7 @@ bool MyApp::OnInit(void) return false; } -#if wxCHECK_VERSION(2,9,0) m_testFont.Create(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxS("Arial")); -#else - m_testFont.Create(10, wxSWISS, wxNORMAL, wxNORMAL, false, wxS("Arial")); -#endif g_printData = new wxPrintData; // You could set an initial paper size here @@ -640,8 +626,11 @@ void MyFrame::Draw(wxDC& dc) dc.SetUserScale(coordScaleX, coordScaleY); dc.SetPen( wxPen(*wxBLACK,0,wxPENSTYLE_DOT_DASH) ); + dc.SetBrush(wxBrush(wxColour(64, 128, 64), wxBRUSHSTYLE_CROSSDIAG_HATCH)); dc.DrawEllipse(50, 140, 100, 50); + dc.SetPen(*wxRED_PEN); + dc.SetBrush(*wxCYAN_BRUSH); dc.SetUserScale(fontScaleX, fontScaleY); dc.DrawText(wxS("Test message: this is in 10 point text"), wxRound(10 * txtPosScaleX), wxRound(180 * txtPosScaleY)); @@ -919,8 +908,6 @@ void MyFrame::WriteRichTextBuffer() wxIMAGE_QUALITY_HIGH ); -#if wxMAJOR_VERSION > 2 || (wxMAJOR_VERSION == 2 && wxMINOR_VERSION == 9) - r.SetDefaultStyle(wxRichTextAttr()); r.BeginSuppressUndo(); @@ -934,7 +921,7 @@ void MyFrame::WriteRichTextBuffer() r.BeginFontSize(14); - wxString lineBreak = (wxChar) 29; + wxString lineBreak = wxUniChar(29); r.WriteText(wxString(wxS("Welcome to wxRichTextCtrl, a wxWidgets control")) + lineBreak + wxS("for editing and presenting styled text and images\n")); r.EndFontSize(); @@ -1190,208 +1177,6 @@ void MyFrame::WriteRichTextBuffer() r.Thaw(); r.EndSuppressUndo(); - -#else -// 2.8.x implementation - r.SetDefaultStyle(wxRichTextAttr()); - - r.BeginSuppressUndo(); - - r.BeginParagraphSpacing(0, 20); - - r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE); - r.BeginBold(); - - r.BeginFontSize(14); - - wxString lineBreak = (wxChar) 29; - - r.WriteText(wxString(wxS("Welcome to wxRichTextCtrl, a wxWidgets control")) + lineBreak + wxS("for editing and presenting styled text and images\n")); - r.EndFontSize(); - //r.Newline(); - - r.BeginItalic(); - r.WriteText(wxS("by Julian Smart")); - r.EndItalic(); - - r.EndBold(); - r.Newline(); - - r.WriteImage(imgZebra); - - r.Newline(); - r.Newline(); - - r.EndAlignment(); - - int i; - for ( i = 0; i < 10; ++i) - { - - r.WriteText(wxS("What can you do with this thing? ")); - - r.WriteImage(imgSmile); - r.WriteText(wxS(" Well, you can change text ")); - - r.BeginTextColour(wxColour(255, 0, 0)); - r.WriteText(wxS("colour, like this red bit.")); - r.EndTextColour(); - - wxRichTextAttr backgroundColourAttr; - backgroundColourAttr.SetBackgroundColour(*wxGREEN); - backgroundColourAttr.SetTextColour(wxColour(0, 0, 255)); - r.BeginStyle(backgroundColourAttr); - r.WriteText(wxS(" And this blue on green bit.")); - r.EndStyle(); - - r.WriteText(wxS(" Naturally you can make things ")); - r.BeginBold(); - r.WriteText(wxS("bold ")); - r.EndBold(); - r.BeginItalic(); - r.WriteText(wxS("or italic ")); - r.EndItalic(); - r.BeginUnderline(); - r.WriteText(wxS("or underlined.")); - r.EndUnderline(); - - r.BeginFontSize(14); - r.WriteText(wxS(" Different font sizes on the same line is allowed, too.")); - r.EndFontSize(); - - r.WriteText(wxS(" Next we'll show an indented paragraph.")); - - r.Newline(); - - r.BeginLeftIndent(60); - r.WriteText(wxS("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable.")); - r.Newline(); - - r.EndLeftIndent(); - - r.WriteText(wxS("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40).")); - - r.Newline(); - - r.BeginLeftIndent(100, -40); - - r.WriteText(wxS("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable.")); - r.Newline(); - - r.EndLeftIndent(); - - r.WriteText(wxS("Numbered bullets are possible, again using subindents:")); - r.Newline(); - - r.BeginNumberedBullet(1, 100, 60); - r.WriteText(wxS("This is my first item. Note that wxRichTextCtrl can apply numbering and bullets automatically based on list styles, but this list is formatted explicitly by setting indents.")); - r.Newline(); - - r.EndNumberedBullet(); - - r.BeginNumberedBullet(2, 100, 60); - r.WriteText(wxS("This is my second item.")); - r.Newline(); - - r.EndNumberedBullet(); - - r.WriteText(wxS("The following paragraph is right-indented:")); - r.Newline(); - - r.BeginRightIndent(200); - - r.WriteText(wxS("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable.")); - r.Newline(); - - r.EndRightIndent(); - - r.WriteText(wxS("The following paragraph is right-aligned with 1.5 line spacing:")); - r.Newline(); - - r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT); - r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF); - r.WriteText(wxS("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable.")); - r.Newline(); - r.EndLineSpacing(); - r.EndAlignment(); - - wxArrayInt tabs; - tabs.Add(400); - tabs.Add(600); - tabs.Add(800); - tabs.Add(1000); - wxTextAttrEx attr; - attr.SetFlags(wxTEXT_ATTR_TABS); - attr.SetTabs(tabs); - r.SetDefaultStyle(attr); - - r.WriteText(wxS("This line contains tabs:\tFirst tab\tSecond tab\tThird tab")); - r.Newline(); - - r.WriteText(wxS("Other notable features of wxRichTextCtrl include:")); - r.Newline(); - - r.BeginSymbolBullet(wxS('*'), 100, 60); - r.WriteText(wxS("Compatibility with wxTextCtrl API")); - r.Newline(); - r.EndSymbolBullet(); - - r.BeginSymbolBullet(wxS('*'), 100, 60); - r.WriteText(wxS("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()")); - r.Newline(); - r.EndSymbolBullet(); - - r.BeginSymbolBullet(wxS('*'), 100, 60); - r.WriteText(wxS("XML loading and saving")); - r.Newline(); - r.EndSymbolBullet(); - - r.BeginSymbolBullet(wxS('*'), 100, 60); - r.WriteText(wxS("Undo/Redo, with batching option and Undo suppressing")); - r.Newline(); - r.EndSymbolBullet(); - - r.BeginSymbolBullet(wxS('*'), 100, 60); - r.WriteText(wxS("Clipboard copy and paste")); - r.Newline(); - r.EndSymbolBullet(); - - r.BeginSymbolBullet(wxS('*'), 100, 60); - r.WriteText(wxS("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles")); - r.Newline(); - r.EndSymbolBullet(); - - r.BeginSymbolBullet(wxS('*'), 100, 60); - r.WriteText(wxS("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on")); - r.Newline(); - r.EndSymbolBullet(); - - // Make a style suitable for showing a URL - wxRichTextAttr urlStyle; - urlStyle.SetTextColour(*wxBLUE); - urlStyle.SetFontUnderlined(true); - - r.WriteText(wxS("wxRichTextCtrl can also display URLs, such as this one: ")); - r.BeginStyle(urlStyle); - r.BeginURL(wxS("http://www.wxwidgets.org")); - r.WriteText(wxS("The wxWidgets Web Site")); - r.EndURL(); - r.EndStyle(); - r.WriteText(wxS(". Click on the URL to generate an event.")); - - r.Newline(); - - r.WriteText(wxS("Note: this sample content was generated programmatically from within the MyFrame constructor in the demo. The images were loaded from inline XPMs. Enjoy wxRichTextCtrl!")); - - r.Newline(); - } - - r.EndParagraphSpacing(); - - r.EndSuppressUndo(); - -#endif - } #endif @@ -1532,7 +1317,7 @@ bool MyPrintout::OnPrintPage(int page) // Draw page numbers at top left corner of printable area, sized so that // screen size of text matches paper size. MapScreenSizeToPage(); - wxChar buf[200]; + wxStringCharType buf[200]; wxSprintf(buf, wxS("PAGE %d"), page); dc->DrawText(buf, 0, 0); @@ -1740,7 +1525,7 @@ void MyPrintout::DrawPageTwo() } // Writes a header on a page. Margin units are in millimetres. -bool WritePageHeader(wxPrintout *printout, wxDC *dc, const wxChar *text, float mmToLogical) +bool WritePageHeader(wxPrintout* printout, wxDC* dc, const wxStringCharType* text, float mmToLogical) { /* static wxFont *headerFont = (wxFont *) NULL; diff --git a/src/pdfdc.cpp b/src/pdfdc.cpp index 80f26246..41c08980 100644 --- a/src/pdfdc.cpp +++ b/src/pdfdc.cpp @@ -27,6 +27,7 @@ #include "wx/pdfdc.h" #include "wx/pdffontmanager.h" +#include "wx/pdfutility.h" #include @@ -1597,8 +1598,73 @@ wxPdfDCImpl::SetupBrush() { if (MustSetCurrentBrush(curBrush)) { + wxColour brushColour = curBrush.GetColour(); + wxString pdfPatternName; + wxPdfPatternStyle pdfPatternStyle = wxPDF_PATTERNSTYLE_NONE; + switch (curBrush.GetStyle()) + { + case wxBRUSHSTYLE_BDIAGONAL_HATCH: + pdfPatternStyle = wxPDF_PATTERNSTYLE_BDIAGONAL_HATCH; + pdfPatternName = "dcHatchBDiagonal"; + break; + case wxBRUSHSTYLE_CROSSDIAG_HATCH: + pdfPatternStyle = wxPDF_PATTERNSTYLE_CROSSDIAG_HATCH; + pdfPatternName = "dcHatchCrossDiag"; + break; + case wxBRUSHSTYLE_FDIAGONAL_HATCH: + pdfPatternStyle = wxPDF_PATTERNSTYLE_FDIAGONAL_HATCH; + pdfPatternName = "dcHatchFDiagonal"; + break; + case wxBRUSHSTYLE_CROSS_HATCH: + pdfPatternStyle = wxPDF_PATTERNSTYLE_CROSS_HATCH; + pdfPatternName = "dcHatchCross"; + break; + case wxBRUSHSTYLE_HORIZONTAL_HATCH: + pdfPatternStyle = wxPDF_PATTERNSTYLE_HORIZONTAL_HATCH; + pdfPatternName = "dcHatchHorizontal"; + break; + case wxBRUSHSTYLE_VERTICAL_HATCH: + pdfPatternStyle = wxPDF_PATTERNSTYLE_VERTICAL_HATCH; + pdfPatternName = "dcHatchVertical"; + break; + case wxBRUSHSTYLE_STIPPLE: + pdfPatternStyle = wxPDF_PATTERNSTYLE_IMAGE; + pdfPatternName = "dcImagePattern"; + break; + case wxBRUSHSTYLE_STIPPLE_MASK: + case wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE: + // Stipple mask / stipple mask opaque not implemented + case wxBRUSHSTYLE_TRANSPARENT: + case wxBRUSHSTYLE_SOLID: + default: + break; + } + if (pdfPatternStyle >= wxPDF_PATTERNSTYLE_FIRST_HATCH && pdfPatternStyle <= wxPDF_PATTERNSTYLE_LAST_HATCH) + { + wxString patternName = pdfPatternName + wxString::Format(wxS("#%8x"), brushColour.GetRGBA()); + m_pdfDocument->AddPattern(patternName, pdfPatternStyle, ScaleLogicalToPdfXRel(6), ScaleLogicalToPdfYRel(6), brushColour); + m_pdfDocument->SetFillPattern(patternName); + } + else if (pdfPatternStyle == wxPDF_PATTERNSTYLE_IMAGE) + { + wxImage imagePattern = curBrush.GetStipple()->ConvertToImage(); + if (imagePattern.Ok()) + { + imagePattern.SetMask(false); + wxString patternName = pdfPatternName + wxString::Format(wxS("#%d"), IncreaseImageCounter()); + m_pdfDocument->AddPattern(patternName, pdfPatternStyle, ScaleLogicalToPdfXRel(imagePattern.GetWidth()), ScaleLogicalToPdfYRel(imagePattern.GetHeight()), brushColour); + m_pdfDocument->SetFillPattern(patternName); + } + else + { + m_pdfDocument->SetFillColour(curBrush.GetColour().Red(), curBrush.GetColour().Green(), curBrush.GetColour().Blue()); + } + } + else + { + m_pdfDocument->SetFillColour(curBrush.GetColour().Red(), curBrush.GetColour().Green(), curBrush.GetColour().Blue()); + } m_pdfBrush = curBrush; - m_pdfDocument->SetFillColour(curBrush.GetColour().Red(), curBrush.GetColour().Green(), curBrush.GetColour().Blue()); } } else diff --git a/src/pdfdocument.cpp b/src/pdfdocument.cpp index 497a4d9c..96c60ac8 100644 --- a/src/pdfdocument.cpp +++ b/src/pdfdocument.cpp @@ -2481,6 +2481,75 @@ wxPdfDocument::AddPattern(const wxString& patternName, const wxImage& image, dou return isValid; } +bool +wxPdfDocument::AddPattern(const wxString& patternName, int templateId, double width, double height) +{ + bool isValid = true; + wxPdfPatternMap::iterator patternIter = m_patterns->find(patternName); + if (patternIter == m_patterns->end()) + { + wxPdfTemplatesMap::iterator templateIter = m_templates->find(templateId); + + if (templateIter != m_templates->end() && width > 0 && height > 0) + { + + // Register new pattern + wxPdfPattern* pattern; + int i = (int)m_patterns->size() + 1; + pattern = new wxPdfPattern(i, width, height, templateId); + (*m_patterns)[patternName] = pattern; + } + else + { + isValid = false; + if (templateIter == m_templates->end()) + { + wxLogError(wxString(wxS("wxPdfDocument::AddPattern: ")) + + wxString(_("Invalid template id."))); + } + else + { + wxLogError(wxString(wxS("wxPdfDocument::AddPattern: ")) + + wxString::Format(_("Invalid width (%.1f) and/or height (%.1f)."), width, height)); + } + } + } + return isValid; +} + +bool +wxPdfDocument::AddPattern(const wxString& patternName, wxPdfPatternStyle patternStyle, double width, double height, const wxColour& drawColour, const wxColour& fillColour) +{ + bool isValid = true; + wxPdfPatternMap::iterator patternIter = m_patterns->find(patternName); + if (patternIter == m_patterns->end()) + { + if (patternStyle >= wxPDF_PATTERNSTYLE_FIRST_HATCH && patternStyle <= wxPDF_PATTERNSTYLE_LAST_HATCH && width > 0 && height > 0) + { + // Register new pattern + wxPdfPattern* pattern; + int i = (int) m_patterns->size() + 1; + pattern = new wxPdfPattern(i, width, height, patternStyle, drawColour, fillColour); + (*m_patterns)[patternName] = pattern; + } + else + { + isValid = false; + if (!(patternStyle >= wxPDF_PATTERNSTYLE_FIRST_HATCH && patternStyle <= wxPDF_PATTERNSTYLE_LAST_HATCH)) + { + wxLogError(wxString(wxS("wxPdfDocument::AddPattern: ")) + + wxString(_("Invalid pattern style."))); + } + if (width <= 0 || height <= 0) + { + wxLogError(wxString(wxS("wxPdfDocument::AddPattern: ")) + + wxString::Format(_("Invalid width (%.1f) and/or height (%.1f)."), width, height)); + } + } + } + return isValid; +} + void wxPdfDocument::SetDrawColour(const wxColour& colour) { diff --git a/src/pdfkernel.cpp b/src/pdfkernel.cpp index f1769682..bff276d0 100644 --- a/src/pdfkernel.cpp +++ b/src/pdfkernel.cpp @@ -2224,6 +2224,17 @@ wxPdfDocument::PutSpotColours() } } +void +wxPdfDocument::InitPatternIds() +{ + wxPdfPatternMap::iterator patternIter = m_patterns->begin(); + for (patternIter = m_patterns->begin(); patternIter != m_patterns->end(); patternIter++) + { + wxPdfPattern* pattern = patternIter->second; + pattern->SetObjIndex(GetNewObjId()); + } +} + void wxPdfDocument::PutPatterns() { @@ -2231,33 +2242,131 @@ wxPdfDocument::PutPatterns() for (patternIter = m_patterns->begin(); patternIter != m_patterns->end(); patternIter++) { wxPdfPattern* pattern = patternIter->second; - NewObj(); - pattern->SetObjIndex(m_n); + NewObj(pattern->GetObjIndex()); Out("<<"); Out("/Type /Pattern"); Out("/PatternType 1"); Out("/PaintType 1"); Out("/TilingType 1"); - OutAscii(wxString(wxS("/BBox [0 0 ")) + - wxPdfUtility::Double2String(pattern->GetWidth() * m_k, 4) + wxS(" ") + - wxPdfUtility::Double2String(pattern->GetHeight() * m_k, 4) + wxS("]")); - OutAscii(wxString(wxS("/XStep ")) + - wxPdfUtility::Double2String(pattern->GetWidth() * m_k, 4)); - OutAscii(wxString(wxS("/YStep ")) + - wxPdfUtility::Double2String(pattern->GetHeight() * m_k, 4)); - wxPdfImage* image = pattern->GetImage(); - OutAscii(wxString::Format(wxS("/Resources << /XObject << /I%d %d 0 R >> >>"), image->GetIndex(), image->GetObjIndex())); - Out("/Matrix [ 1 0 0 1 0 0 ]"); - - wxString sdata = wxString::Format(wxS("q ")) + - wxPdfUtility::Double2String(pattern->GetWidth() * m_k, 4) + wxS(" 0 0 ") + - wxPdfUtility::Double2String(pattern->GetHeight() * m_k, 4) + wxS(" 0 0 cm ") + - wxString::Format(wxS("/I%d Do Q"), image->GetIndex()); - wxMemoryOutputStream mos; - mos.Write(sdata.ToAscii(), sdata.Length()); - OutAscii(wxString(wxS("/Length ")) + wxString::Format(wxS("%lu"), (unsigned long) CalculateStreamLength(mos.TellO()))); - Out(">>"); - PutStream(mos); + if (pattern->GetPatternStyle() == wxPDF_PATTERNSTYLE_IMAGE || + pattern->GetPatternStyle() == wxPDF_PATTERNSTYLE_TEMPLATE ) + { + OutAscii(wxString(wxS("/BBox [0 0 ")) + + wxPdfUtility::Double2String(pattern->GetWidth() * m_k, 4) + wxS(" ") + + wxPdfUtility::Double2String(pattern->GetHeight() * m_k, 4) + wxS("]")); + OutAscii(wxString(wxS("/XStep ")) + + wxPdfUtility::Double2String(pattern->GetWidth() * m_k, 4)); + OutAscii(wxString(wxS("/YStep ")) + + wxPdfUtility::Double2String(pattern->GetHeight() * m_k, 4)); + if (pattern->GetPatternStyle() == wxPDF_PATTERNSTYLE_IMAGE) + { + wxPdfImage* image = pattern->GetImage(); + OutAscii(wxString::Format(wxS("/Resources << /XObject << /I%d %d 0 R >> >>"), image->GetIndex(), image->GetObjIndex())); + Out("/Matrix [ 1 0 0 1 0 0 ]"); + + wxString sdata = wxString(wxS("q ")) + + wxPdfUtility::Double2String(pattern->GetWidth() * m_k, 4) + wxS(" 0 0 ") + + wxPdfUtility::Double2String(pattern->GetHeight() * m_k, 4) + wxS(" 0 0 cm ") + + wxString::Format(wxS("/I%d Do Q"), image->GetIndex()); + wxMemoryOutputStream mos; + mos.Write(sdata.ToAscii(), sdata.Length()); + OutAscii(wxString(wxS("/Length ")) + wxString::Format(wxS("%lu"), (unsigned long)CalculateStreamLength(mos.TellO()))); + Out(">>"); + PutStream(mos); + } + else + { + int templateId = pattern->GetTemplateId(); + wxPdfTemplate* tpl = (*m_templates)[templateId]; + OutAscii(wxString(wxS("/Resources << /XObject << ")) + m_templatePrefix + wxString::Format(wxS("%d %d 0 R >> >>"), tpl->GetIndex(), tpl->GetObjIndex())); + Out("/Matrix [ 1 0 0 1 0 0 ]"); + double x, y, w, h; + w = pattern->GetWidth(); + h = pattern->GetHeight(); + x = tpl->GetX(); + y = tpl->GetY(); + GetTemplateSize(templateId, w, h); + + double xScale = w / tpl->GetWidth(); + double yScale = h / tpl->GetHeight(); + double xTrans = (x - xScale * tpl->GetX()) * m_k; + double yTrans = (y - yScale * tpl->GetY()) * m_k; + wxString sdata = wxString(wxS("q ")) + + wxPdfUtility::Double2String(xScale, 4) + wxString(wxS(" 0 0 ")) + + wxPdfUtility::Double2String(yScale, 4) + wxString(wxS(" ")) + + wxPdfUtility::Double2String(xTrans, 2) + wxString(wxS(" ")) + + wxPdfUtility::Double2String(yTrans, 2) + wxString(wxS(" cm ")) + + m_templatePrefix + wxString::Format(wxS("%d Do Q"), tpl->GetIndex()); + wxMemoryOutputStream mos; + mos.Write(sdata.ToAscii(), sdata.Length()); + OutAscii(wxString(wxS("/Length ")) + wxString::Format(wxS("%lu"), (unsigned long)CalculateStreamLength(mos.TellO()))); + Out(">>"); + PutStream(mos); + } + } + else + { + OutAscii(wxString(wxS("/BBox [0 0 10 10]"))); + OutAscii(wxString(wxS("/XStep 10"))); + OutAscii(wxString(wxS("/YStep 10"))); + OutAscii(wxString(wxS("/Resources << >>"))); + wxString patternData; + double corrFactor = 1.0; + switch (pattern->GetPatternStyle()) + { + case wxPDF_PATTERNSTYLE_BDIAGONAL_HATCH: + patternData = "0 0 m 10 10 l -1 9 m 1 11 l 9 -1 m 11 1 l"; + break; + case wxPDF_PATTERNSTYLE_CROSSDIAG_HATCH: + patternData = "0 0 m 10 10 l 0 10 m 10 0 l"; + break; + case wxPDF_PATTERNSTYLE_FDIAGONAL_HATCH: + patternData = "0 10 m 10 0 l -1 1 m 1 -1 l 9 11 m 11 9 l"; + break; + case wxPDF_PATTERNSTYLE_CROSS_HATCH: + patternData = "0 5 m 10 5 l 5 0 m 5 10 l"; + break; + case wxPDF_PATTERNSTYLE_HORIZONTAL_HATCH: + patternData = "0 5 m 10 5 l"; + break; + case wxPDF_PATTERNSTYLE_VERTICAL_HATCH: + patternData = "5 0 m 5 10 l"; + break; + case wxPDF_PATTERNSTYLE_HERRINGBONE_HATCH: + patternData = wxString(wxS("1.25 1.25 m 8.75 1.25 l 0 3.75 m 6.25 3.75 l 8.75 3.75 m 10 3.75 l")) + + wxS(" 0 6.25 m 3.75 6.25 l 6.25 6.25 m 10 6.25 l 0 8.75 m 1.25 8.75 l 3.75 8.75 m 10 8.75 l") + + wxS(" 1.25 0 m 1.25 3.75 l 1.25 6.25 m 1.25 10 l 3.75 0 m 3.75 1.25 l 3.75 3.75 m 3.75 10 l") + + wxS(" 6.25 1.25 m 6.25 8.75 l 8.75 0 m 8.75 6.25 l 8.75 8.75 m 8.75 10 l"); + corrFactor = 4; + break; + case wxPDF_PATTERNSTYLE_BASKETWEAVE_HATCH: + patternData = wxString(wxS("0 1.25 m 10 1.25 l 0 6.25 m 10 6.25 l 3.75 0 m 3.75 10 l 8.75 0 m 8.75 10 l")) + + wxS(" 0 3.75 m 3.75 3.75 l 8.75 3.75 m 10 3.75 l 3.75 8.75 m 8.75 8.75 l") + + wxS(" 1.25 0 m 1.25 1.25 l 1.25 6.25 m 1.25 10 l 6.25 1.25 m 6.25 6.25 l"); + corrFactor = 4; + break; + case wxPDF_PATTERNSTYLE_BRICK_HATCH: + patternData = "0 3 m 10 3 l 0 8 m 10 8 l 3 0 m 3 3 l 3 8 m 3 10 l 8 3 m 8 8 l"; + corrFactor = 2; + break; + } + OutAscii(wxString(wxS("/Matrix [")) + + wxPdfUtility::Double2String((pattern->GetWidth() * m_k) / 10.0 * corrFactor, 4) + wxS(" 0 0 ") + + wxPdfUtility::Double2String((pattern->GetHeight() * m_k) / 10.0 * corrFactor, 4) + wxS(" 0 0]")); + wxString background; + if (pattern->HasFillColour()) + { + background = wxPdfUtility::RGB2String(pattern->GetFillColour()) + wxS(" rg 0 0 10 10 re f "); + } + wxString sdata = wxString::Format(wxS("q ")) + background + + wxPdfUtility::RGB2String(pattern->GetDrawColour()) + wxS(" RG 2 J 0.5 w ") + + patternData + wxS(" S Q"); + wxMemoryOutputStream mos; + mos.Write(sdata.ToAscii(), sdata.Length()); + OutAscii(wxString(wxS("/Length ")) + wxString::Format(wxS("%lu"), (unsigned long)CalculateStreamLength(mos.TellO()))); + Out(">>"); + PutStream(mos); + } Out("endobj"); } } @@ -2435,8 +2544,9 @@ wxPdfDocument::PutResources() PutShaders(); PutFonts(); PutImages(); - PutPatterns(); + InitPatternIds(); PutTemplates(); + PutPatterns(); PutImportedObjects(); PutSpotColours(); PutLayers(); diff --git a/src/pdfpattern.cpp b/src/pdfpattern.cpp index ea243df5..1175ff2a 100644 --- a/src/pdfpattern.cpp +++ b/src/pdfpattern.cpp @@ -23,10 +23,25 @@ #include "wx/pdfpattern.h" wxPdfPattern::wxPdfPattern(int index, double width, double height) - : m_objIndex(0), m_index(index), m_width(width), m_height(height) + : m_objIndex(0), m_index(index), m_width(width), m_height(height), m_patternStyle(wxPDF_PATTERNSTYLE_IMAGE) { } +wxPdfPattern::wxPdfPattern(int index, double width, double height, int templateId) + : m_objIndex(0), m_index(index), m_width(width), m_height(height), m_patternStyle(wxPDF_PATTERNSTYLE_TEMPLATE), m_templateId(templateId) +{ +} + +wxPdfPattern::wxPdfPattern(int index, double width, double height, wxPdfPatternStyle patternStyle, const wxColour& drawColour, const wxColour& fillColour) + : m_objIndex(0), m_index(index), m_width(width), m_height(height), m_patternStyle(patternStyle), m_drawColour(drawColour) +{ + m_hasFillColour = fillColour.IsOk(); + if (m_hasFillColour) + { + m_fillColour = fillColour; + } +} + wxPdfPattern::wxPdfPattern(const wxPdfPattern& pattern) { m_objIndex = pattern.m_objIndex; @@ -34,4 +49,8 @@ wxPdfPattern::wxPdfPattern(const wxPdfPattern& pattern) m_width = pattern.m_width; m_height = pattern.m_height; m_image = pattern.m_image; + m_templateId = pattern.m_templateId; + m_patternStyle = pattern.m_patternStyle; + m_drawColour = pattern.m_drawColour; + m_fillColour = pattern.m_fillColour; }