1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2011 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef FONT_SUPPORT_H_ 8 #define FONT_SUPPORT_H_ 9 10 #include <list> 11 12 #include "Wt/WDllDefs.h" 13 14 #ifdef WT_TARGET_JAVA 15 #define WT_FONTSUPPORT_SIMPLE 16 #endif // WT_TARGET_JAVA 17 #ifdef WT_FONTSUPPORT_SIMPLE 18 #include <string> 19 #endif // WT_FONTSUPPORT_SIMPLE 20 #ifdef WT_FONTSUPPORT_PANGO 21 #include <pango/pango.h> 22 #endif // WT_FONTSUPPORT_PANGO 23 #ifdef WT_FONTSUPPORT_DIRECTWRITE 24 #include <dwrite.h> 25 #endif // WT_FONTSUPPORT_DIRECTWRITE 26 27 #include "Wt/WFont.h" 28 #include "Wt/WPaintDevice.h" 29 30 namespace Wt { 31 32 /* 33 * A private utility class that provides improved font matching. 34 * 35 * This utility class uses libpango for font selection and layout if 36 * available, otherwise uses a simple font matching which choses a 37 * single font and does not take into account its supported glyphs. 38 */ 39 class FontSupport 40 { 41 public: 42 #ifndef WT_TARGET_JAVA 43 class Bitmap { 44 public: 45 Bitmap(int width, int height); 46 ~Bitmap(); 47 width()48 int width() const { return width_; } height()49 int height() const { return height_; } pitch()50 int pitch() const { return pitch_; } 51 value(int x,int y)52 unsigned char value(int x, int y) const { return buffer_[y * pitch_ + x]; } 53 buffer()54 unsigned char *buffer() { return buffer_; } 55 56 private: 57 int width_, height_, pitch_; 58 59 unsigned char *buffer_; 60 }; 61 #endif 62 63 /* For limiting font formats in FontMatch constructor 64 */ 65 enum EnabledFontFormats { AnyFont, // Any available font format 66 TrueTypeOnly // Only .ttf or .ttc fonts 67 }; 68 69 class FontMatch { 70 public: 71 #ifdef WT_FONTSUPPORT_SIMPLE 72 73 FontMatch(); 74 FontMatch(const std::string& fileName, double quality); 75 matched()76 bool matched() const { return quality_ > 0; } 77 fileName()78 std::string fileName() const { return file_; } setFileName(const std::string & file)79 void setFileName(const std::string &file) { file_ = file; } quality()80 double quality() const { return quality_; } setQuality(double quality)81 void setQuality(double quality) { quality_ = quality; } 82 83 #endif // WT_FONTSUPPORT_SIMPLE 84 85 #ifdef WT_FONTSUPPORT_PANGO 86 87 FontMatch(PangoFont *font, PangoFontDescription *desc); 88 matched()89 bool matched() const { return true; } 90 std::string fileName() const; pangoFont()91 PangoFont *pangoFont() const { return font_; } pangoFontDescription()92 PangoFontDescription *pangoFontDescription() const { return desc_; } 93 94 #endif // WT_FONTSUPPORT_PANGO 95 96 #ifdef WT_FONTSUPPORT_DIRECTWRITE 97 FontMatch(); 98 FontMatch(IDWriteTextFormat *textFormat, 99 IDWriteFontFamily *fontFamily, 100 IDWriteFont *font, 101 std::string fontFamilyFileName); 102 ~FontMatch(); 103 104 FontMatch(const FontMatch &other); 105 FontMatch &operator=(const FontMatch &other); 106 #ifdef WT_CXX11 107 FontMatch(FontMatch &&other); 108 FontMatch &operator=(FontMatch &&other); 109 #endif // WT_CXX11 110 111 bool matched() const; 112 std::string fileName() const; 113 114 std::wstring fontFamilyName() const; 115 116 // For use in WRasterImage-d2d1.C textFormat()117 IDWriteTextFormat *textFormat() { return textFormat_; } fontFamily()118 IDWriteFontFamily *fontFamily() { return fontFamily_; } font()119 IDWriteFont *font() { return font_; } 120 #endif // WT_FONTSUPPORT_DIRECTWRITE 121 private: 122 123 #ifdef WT_FONTSUPPORT_SIMPLE 124 std::string file_; 125 double quality_; 126 #endif // WT_FONTSUPPORT_SIMPLE 127 #ifdef WT_FONTSUPPORT_PANGO 128 mutable PangoFont *font_; 129 PangoFontDescription *desc_; 130 #endif // WT_FONTSUPPORT_PANGO 131 #ifdef WT_FONTSUPPORT_DIRECTWRITE 132 IDWriteTextFormat *textFormat_; 133 IDWriteFontFamily *fontFamily_; 134 IDWriteFont *font_; 135 mutable std::string fontFamilyFileName_; 136 #endif // WT_FONTSUPPORT_DIRECTWRITE 137 }; 138 139 FontSupport(WPaintDevice *device, EnabledFontFormats enabledFontFormats=AnyFont); 140 ~FontSupport(); 141 142 void setDevice(WPaintDevice *device); 143 144 /* 145 * Returns the best matching true type font. 146 */ 147 FontMatch matchFont(const WFont& f) const; 148 149 /* 150 * Returns font metrics 151 */ 152 WFontMetrics fontMetrics(const WFont& f); 153 154 /* 155 * Measures the text, taking into account actual font choices. 156 * 157 * When there is a device_, the actual measurements are delegated to the 158 * device. Otherwise, pango is used for measurements. 159 */ 160 WTextItem measureText(const WFont& f, const WString& text, double maxWidth, 161 bool wordWrap); 162 163 /* 164 * Draws the text, using pango for font choices, but delegating the actual 165 * drawing to the device 166 * 167 * Precondition: device_ != nullptr 168 */ 169 void drawText(const WFont& f, 170 const WRectF& rect, 171 WFlags<AlignmentFlag> alignmentFlags, const WString& text); 172 173 /* 174 * Returns true while in measureText() or drawText() 175 */ 176 bool busy() const; 177 178 /* 179 * Returns the currently matched font path (while busy()). 180 */ 181 std::string drawingFontPath() const; 182 183 /* 184 * Returns whether the implementation can actually render (which is only 185 * the case for pango 186 */ 187 bool canRender() const; 188 189 #ifndef WT_TARGET_JAVA 190 /* 191 * Draws the text, using pango and libfreetype to do the actual rendering 192 * 193 * Precondition: device_ == nullptr 194 */ 195 void drawText(const WFont& f, 196 const WRectF& rect, 197 const WTransform& transform, 198 Bitmap& bitmap, 199 WFlags<AlignmentFlag> alignmentFlags, const WString& text); 200 #endif 201 202 /* 203 * If libpango support is available, this is a no-op. 204 */ 205 void addFontCollection(const std::string& directory, bool recursive = true); 206 207 #ifdef WT_FONTSUPPORT_DIRECTWRITE 208 /* 209 * Direct access to IDWriteFactory for WRasterImage-d2d1 210 */ writeFactory()211 IDWriteFactory *writeFactory() { return writeFactory_; } 212 #endif // WT_FONTSUPPORT_DIRECTWRITE 213 214 private: 215 WPaintDevice *device_; 216 217 #ifdef WT_FONTSUPPORT_SIMPLE 218 219 struct FontCollection { 220 std::string directory; 221 bool recursive; 222 }; 223 224 std::vector<FontCollection> fontCollections_; 225 226 struct Matched { 227 WFont font; 228 FontMatch match; 229 MatchedMatched230 Matched() : font(), match() { } 231 }; 232 233 typedef std::list<Matched> MatchCache; 234 mutable MatchCache cache_; 235 236 const WFont *font_; 237 238 FontMatch matchFont(const WFont& font, const std::string& directory, 239 bool recursive) const; 240 void matchFont(const WFont& font, 241 const std::vector<std::string>& fontNames, 242 const std::string& path, 243 bool recursive, 244 FontMatch& match) const; 245 void matchFont(const WFont& font, 246 const std::vector<std::string>& fontNames, 247 const std::string& path, 248 FontMatch& match) const; 249 250 #endif // WT_FONTSUPPORT_SIMPLE 251 252 #ifdef WT_FONTSUPPORT_PANGO 253 254 PangoContext *context_; 255 PangoFont *currentFont_; 256 EnabledFontFormats enabledFontFormats_; 257 258 struct Matched { 259 WFont font; 260 PangoFont *match; 261 PangoFontDescription *desc; 262 MatchedMatched263 Matched() : font(), match(nullptr), desc(nullptr) { } MatchedMatched264 Matched(const WFont& f, PangoFont *m, PangoFontDescription *d) : font(f), match(m), desc(d) { } 265 }; 266 267 typedef std::list<Matched> MatchCache; 268 mutable MatchCache cache_; 269 270 PangoFontDescription *createFontDescription(const WFont& f) const; 271 static std::string fontPath(PangoFont *font); 272 GList *layoutText(const WFont& font, const std::string& utf8, 273 std::vector<PangoGlyphString *>& glyphs, int& width); 274 275 friend class FontMatch; 276 277 #endif // WT_FONTSUPPORT_PANGO 278 279 #ifdef WT_FONTSUPPORT_DIRECTWRITE 280 EnabledFontFormats enabledFontFormats_; 281 282 IDWriteFactory *writeFactory_; 283 284 const WFont *font_; 285 std::string drawingFontPath_; 286 287 struct Matched { 288 WFont font; 289 FontMatch match; 290 MatchedMatched291 Matched() 292 : font(), match() 293 { } 294 MatchedMatched295 Matched(const WFont &f, 296 FontMatch &&m) 297 : font(f), match(m) 298 { } 299 }; 300 301 typedef std::list<Matched> MatchCache; 302 mutable MatchCache cache_; 303 304 struct TextFragment { TextFragmentTextFragment305 TextFragment(std::string fontPath, 306 std::size_t start, 307 std::size_t length, 308 double width) 309 : fontPath(fontPath), 310 start(start), 311 length(length), 312 width(width) 313 { } 314 315 std::string fontPath; 316 std::size_t start; 317 std::size_t length; 318 double width; 319 }; 320 class TextFragmentRenderer; 321 322 void layoutText(const WFont &f, std::vector<TextFragment> &v, const std::wstring &s, double &width, double &nextWidth, double maxWidth, bool wordWrap); 323 #endif // WT_FONTSUPPORT_DIRECTWRITE 324 }; 325 326 } 327 328 #endif // FONT_SUPPORT_H_ 329