1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2010 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef WPDF_IMAGE_H_ 8 #define WPDF_IMAGE_H_ 9 10 #include <Wt/WFont.h> 11 #include <Wt/WPaintDevice.h> 12 #include <Wt/WResource.h> 13 #ifdef WT_TARGET_JAVA 14 #include <Wt/WTransform.h> 15 #endif //WT_TARGET_JAVA 16 17 #include <hpdf.h> 18 19 #include <map> 20 21 namespace Wt { 22 23 class FontSupport; 24 class WTransform; 25 26 /*! \class WPdfImage Wt/WPdfImage.h Wt/WPdfImage.h 27 * \brief A paint device for rendering to a PDF. 28 * 29 * A %WPdfImage paint device should be used in conjunction with a 30 * WPainter, and can be used to make a PDF version of a 31 * WPaintedWidget's contents. 32 * 33 * The PDF is generated using <a href="http://libharu.org/">The Haru 34 * Free PDF Library</a>, and this class is included in the library 35 * only if <tt>libharu</tt> was found during the build of the library. 36 * 37 * You can use the image as a resource and specialize handleRequest() 38 * to paint the contents on the fly. Alternatively can also use 39 * write() to serialize to a PDF file (std::ostream). The latter usage 40 * is illustrated by the code below: 41 * 42 * \code Wt::Chart::WCartesianChart 43 * *chart = ... 44 * 45 * Wt::WPdfImage pdfImage("4cm", "3cm"); 46 * { 47 * Wt::WPainter p(&pdfImage); 48 * chart->paint(p); 49 * } 50 * std::ofstream f("chart.pdf", std::ios::out | std::ios::binary); 51 * pdfImage.write(f); 52 * \endcode 53 * 54 * A constructor is provided which allows the generated PDF image to 55 * be embedded directly into a page of a larger <tt>libharu</tt> 56 * document, and this approach is used for example by the WPdfRenderer 57 * to render XHTML to multi-page PDF files. 58 * 59 * Font information is embedded in the PDF. Fonts supported are native 60 * PostScript fonts (Base-14) (only ASCII-7), or true type fonts 61 * (Unicode). See addFontCollection() for more information on how 62 * fonts are located and matched to WFont descriptions. 63 * 64 * This paint device has the following limitations: 65 * - images (WPainter::drawImage()) can only be included from local 66 * files, and only JPG and PNG images are supported. 67 * - drop shadows are not supported. 68 * 69 * \ingroup painting 70 */ 71 class WT_API WPdfImage : public WResource, public WPaintDevice 72 { 73 public: 74 /*! \brief Create a PDF resource that represents a single-page PDF document. 75 * 76 * The single page will have a size \p width x \p height. The PDF 77 * will be using the same DPI (72dpi) as is conventionally used for 78 * the desktop. 79 * 80 * The passed width and height (such as 4 cm by 3 cm) can be specified in 81 * physical units (e.g. 4cm x 3cm), but this will be converted to pixels using 82 * the default DPI used in CSS (96dpi) ! 83 * 84 * \sa write() 85 */ 86 WPdfImage(const WLength& width, const WLength& height); 87 88 /*! \brief Create a PDF paint device to paint inside an existing page. 89 * 90 * The image will be drawn in the existing page, as an image with lower-left 91 * point (\p x, \p y) and size (\p width x \p height). 92 */ 93 WPdfImage(HPDF_Doc pdf, HPDF_Page page, 94 HPDF_REAL x, HPDF_REAL y, HPDF_REAL width, HPDF_REAL height); 95 96 /*! \brief Destructor. 97 */ 98 ~WPdfImage(); 99 100 /*! \brief Adds a font collection. 101 * 102 * If %Wt has been configured to use <tt>libpango</tt>, then font 103 * matching and character selection is done by libpango, which is 104 * seeded with information on installed fonts by fontconfig. In that 105 * case, invocations for this method is ignored. Only TrueType fonts 106 * are supported. 107 * 108 * As of %Wt 3.3.7, only TrueType fonts will be selected by default. 109 * Prior to %Wt 3.3.7, you needed to configure fontconfig (which 110 * is used by pango) to only return TrueType fonts. This can be 111 * done using a fonts.conf configuration %file: 112 * 113 * \code{.xml} 114 * <?xml version='1.0'?> 115 * <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> 116 * <fontconfig> 117 * <selectfont> 118 * <rejectfont> 119 * <glob>*.pfb</glob> 120 * </rejectfont> 121 * </selectfont> 122 * </fontconfig> 123 * \endcode 124 * 125 * You may need to add more glob patterns to exclude other fonts 126 * than TrueType, and also to exclude TrueType fonts which do not 127 * work properly with libharu. 128 * 129 * If %Wt has not been configured to use <tt>libpango</tt>, then 130 * this method may be used to indicate the location of TrueType 131 * fonts. The main drawback compared to libpango is that font 132 * selection is not steered by the need for particular characters, 133 * i.e. font selection is independent from the text's need for 134 * specific characters. Most TrueType fonts provide only partial 135 * unicode support. The provided \p directory will be searched for 136 * fonts (currently only TrueType ".ttf" or ".ttc" fonts). TrueType 137 * fonts are preferable over Base-14 fonts (which are PDF's default 138 * fonts) since they provide partial (or complete) unicode support. 139 * 140 * When using Base-14 fonts, WString::narrow() will be called on text 141 * which may result in loss of information. 142 */ 143 void addFontCollection(const std::string& directory, bool recursive=true); 144 145 #ifdef WT_TARGET_JAVA 146 void setDeviceTransform(const WTransform& deviceTransform); 147 #endif //WT_TARGET_JAVA 148 149 virtual WFlags<PaintDeviceFeatureFlag> features() const override; 150 virtual void setChanged(WFlags<PainterChangeFlag> flags) override; 151 virtual void drawArc(const WRectF& rect, double startAngle, double spanAngle) 152 override; 153 virtual void drawImage(const WRectF& rect, const std::string& imgUri, 154 int imgWidth, int imgHeight, const WRectF& sourceRect) 155 override; 156 virtual void drawLine(double x1, double y1, double x2, double y2) override; 157 virtual void drawRect(const WRectF& rect) override; 158 virtual void drawPath(const WPainterPath& path) override; 159 virtual void drawText(const WRectF& rect, 160 WFlags<AlignmentFlag> alignmentFlags, TextFlag textFlag, 161 const WString& text, const WPointF *clipPoint) 162 override; 163 virtual WTextItem measureText(const WString& text, double maxWidth = -1, 164 bool wordWrap = false) override; 165 virtual WFontMetrics fontMetrics() override; 166 virtual void init() override; 167 virtual void done() override; paintActive()168 virtual bool paintActive() const override { return painter_ != nullptr; } 169 width()170 virtual WLength width() const override { return width_; } height()171 virtual WLength height() const override { return height_; } 172 173 void errorHandler(HPDF_STATUS error_no, HPDF_STATUS detail_no); 174 175 virtual void handleRequest(const Http::Request& request, 176 Http::Response& response) override; 177 178 protected: painter()179 virtual WPainter *painter() const override { return painter_; } setPainter(WPainter * painter)180 virtual void setPainter(WPainter *painter) override { painter_ = painter; } 181 182 private: 183 WLength width_, height_; 184 WPainter *painter_; 185 FontSupport *trueTypeFonts_; 186 187 HPDF_Doc pdf_; 188 HPDF_Page page_; 189 HPDF_Font font_; 190 bool trueTypeFont_; 191 std::map<std::string, const char *> ttfFonts_; 192 WFont currentFont_; 193 std::string currentTtfFont_; 194 std::map<int, HPDF_ExtGState> alphaStrokeExtGStateMap_; 195 std::map<int, HPDF_ExtGState> alphaFillExtGStateMap_; 196 197 bool myPdf_; 198 double x_, y_; 199 200 double fontSize_; 201 202 void paintPath(); 203 void drawPlainPath(const WPainterPath& path); 204 void applyTransform(const WTransform& f); 205 void setStrokeColor(WColor color); 206 void setFillColor(WColor color); 207 }; 208 209 } 210 211 #endif // WPDF_IMAGE_H_ 212