David PHAM-VAN

Add more font drawing options

@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 - Fix Bullet widget styling 8 - Fix Bullet widget styling
9 - Fix HSV and HSL Color constructors 9 - Fix HSV and HSL Color constructors
10 - Add PageTheme.copyWith 10 - Add PageTheme.copyWith
  11 +- Add more font drawing options
11 12
12 ## 1.4.1 13 ## 1.4.1
13 14
@@ -20,6 +20,32 @@ part of pdf; @@ -20,6 +20,32 @@ part of pdf;
20 20
21 enum PdfLineCap { joinMiter, joinRound, joinBevel } 21 enum PdfLineCap { joinMiter, joinRound, joinBevel }
22 22
  23 +enum PdfTextRenderingMode {
  24 + /// Fill text
  25 + fill,
  26 +
  27 + /// Stroke text
  28 + stroke,
  29 +
  30 + /// Fill, then stroke text
  31 + fillAndStroke,
  32 +
  33 + /// Neither fill nor stroke text (invisible)
  34 + invisible,
  35 +
  36 + /// Fill text and add to path for clipping
  37 + fillAndClip,
  38 +
  39 + /// Stroke text and add to path for clipping
  40 + strokeAndClip,
  41 +
  42 + /// Fill, then stroke text and add to path for clipping
  43 + fillStrokeAndClip,
  44 +
  45 + /// Add text to path for clipping
  46 + clip
  47 +}
  48 +
23 @immutable 49 @immutable
24 class _PdfGraphicsContext { 50 class _PdfGraphicsContext {
25 const _PdfGraphicsContext({@required this.ctm}) : assert(ctm != null); 51 const _PdfGraphicsContext({@required this.ctm}) : assert(ctm != null);
@@ -213,7 +239,18 @@ class PdfGraphics { @@ -213,7 +239,18 @@ class PdfGraphics {
213 /// @param x coordinate 239 /// @param x coordinate
214 /// @param y coordinate 240 /// @param y coordinate
215 /// @param s String to draw 241 /// @param s String to draw
216 - void drawString(PdfFont font, double size, String s, double x, double y) { 242 + void drawString(
  243 + PdfFont font,
  244 + double size,
  245 + String s,
  246 + double x,
  247 + double y, {
  248 + double charSpace = 0,
  249 + double wordSpace = 0,
  250 + double scale = 1,
  251 + PdfTextRenderingMode mode = PdfTextRenderingMode.fill,
  252 + double rise = 0,
  253 + }) {
217 if (!page.fonts.containsKey(font.name)) { 254 if (!page.fonts.containsKey(font.name)) {
218 page.fonts[font.name] = font; 255 page.fonts[font.name] = font;
219 } 256 }
@@ -223,8 +260,28 @@ class PdfGraphics { @@ -223,8 +260,28 @@ class PdfGraphics {
223 buf.putString(' Td ${font.name} '); 260 buf.putString(' Td ${font.name} ');
224 buf.putNum(size); 261 buf.putNum(size);
225 buf.putString(' Tf '); 262 buf.putString(' Tf ');
  263 + if (charSpace != 0) {
  264 + buf.putNum(charSpace);
  265 + buf.putString(' Tc ');
  266 + }
  267 + if (wordSpace != 0) {
  268 + buf.putNum(wordSpace);
  269 + buf.putString(' Tw ');
  270 + }
  271 + if (scale != 1) {
  272 + buf.putNum(scale * 100);
  273 + buf.putString(' Tz ');
  274 + }
  275 + if (rise != 0) {
  276 + buf.putNum(rise);
  277 + buf.putString(' Ts ');
  278 + }
  279 + if (mode != PdfTextRenderingMode.fill) {
  280 + buf.putString('${mode.index} Tr ');
  281 + }
  282 + buf.putString('[');
226 buf.putStream(font.putText(s)); 283 buf.putStream(font.putText(s));
227 - buf.putString(' Tj ET\n'); 284 + buf.putString(']TJ ET\n');
228 } 285 }
229 286
230 /// Sets the color for drawing 287 /// Sets the color for drawing
@@ -20,11 +20,11 @@ part of pdf; @@ -20,11 +20,11 @@ part of pdf;
20 20
21 class PdfTtfFont extends PdfFont { 21 class PdfTtfFont extends PdfFont {
22 /// Constructs a [PdfTtfFont] 22 /// Constructs a [PdfTtfFont]
23 - PdfTtfFont(PdfDocument pdfDocument, ByteData bytes) 23 + PdfTtfFont(PdfDocument pdfDocument, ByteData bytes, {bool protect = false})
24 : font = TtfParser(bytes), 24 : font = TtfParser(bytes),
25 super._create(pdfDocument, subtype: '/TrueType') { 25 super._create(pdfDocument, subtype: '/TrueType') {
26 file = PdfObjectStream(pdfDocument, isBinary: true); 26 file = PdfObjectStream(pdfDocument, isBinary: true);
27 - unicodeCMap = PdfUnicodeCmap(pdfDocument); 27 + unicodeCMap = PdfUnicodeCmap(pdfDocument, protect);
28 descriptor = PdfFontDescriptor(this, file); 28 descriptor = PdfFontDescriptor(this, file);
29 widthsObject = PdfArrayObject(pdfDocument, <String>[]); 29 widthsObject = PdfArrayObject(pdfDocument, <String>[]);
30 } 30 }
@@ -19,12 +19,18 @@ @@ -19,12 +19,18 @@
19 part of pdf; 19 part of pdf;
20 20
21 class PdfUnicodeCmap extends PdfObjectStream { 21 class PdfUnicodeCmap extends PdfObjectStream {
22 - PdfUnicodeCmap(PdfDocument pdfDocument) : super(pdfDocument); 22 + PdfUnicodeCmap(PdfDocument pdfDocument, this.protect) : super(pdfDocument);
23 23
24 final List<int> cmap = <int>[0]; 24 final List<int> cmap = <int>[0];
25 25
  26 + final bool protect;
  27 +
26 @override 28 @override
27 void _prepare() { 29 void _prepare() {
  30 + if (protect) {
  31 + cmap.fillRange(1, cmap.length, 0x20);
  32 + }
  33 +
28 buf.putString('/CIDInit/ProcSet findresource begin\n' 34 buf.putString('/CIDInit/ProcSet findresource begin\n'
29 '12 dict begin\n' 35 '12 dict begin\n'
30 'begincmap\n' 36 'begincmap\n'
@@ -144,13 +144,15 @@ class Font { @@ -144,13 +144,15 @@ class Font {
144 } 144 }
145 145
146 class TtfFont extends Font { 146 class TtfFont extends Font {
147 - TtfFont(this.data); 147 + TtfFont(this.data, {this.protect = false});
148 148
149 final ByteData data; 149 final ByteData data;
150 150
  151 + final bool protect;
  152 +
151 @override 153 @override
152 PdfFont buildFont(PdfDocument pdfDocument) { 154 PdfFont buildFont(PdfDocument pdfDocument) {
153 - return PdfTtfFont(pdfDocument, data); 155 + return PdfTtfFont(pdfDocument, data, protect: protect);
154 } 156 }
155 157
156 @override 158 @override
@@ -222,7 +222,9 @@ class _Word extends _Span { @@ -222,7 +222,9 @@ class _Word extends _Span {
222 style.fontSize * textScaleFactor, 222 style.fontSize * textScaleFactor,
223 text, 223 text,
224 point.x + offset.x, 224 point.x + offset.x,
225 - point.y + offset.y); 225 + point.y + offset.y,
  226 + mode: style.renderingMode,
  227 + );
226 } 228 }
227 229
228 @override 230 @override
@@ -112,6 +112,7 @@ class TextStyle { @@ -112,6 +112,7 @@ class TextStyle {
112 this.decorationColor, 112 this.decorationColor,
113 this.decorationStyle, 113 this.decorationStyle,
114 this.decorationThickness, 114 this.decorationThickness,
  115 + this.renderingMode,
115 }) : assert(inherit || color != null), 116 }) : assert(inherit || color != null),
116 assert(inherit || fontNormal != null), 117 assert(inherit || fontNormal != null),
117 assert(inherit || fontBold != null), 118 assert(inherit || fontBold != null),
@@ -127,6 +128,7 @@ class TextStyle { @@ -127,6 +128,7 @@ class TextStyle {
127 assert(inherit || decoration != null), 128 assert(inherit || decoration != null),
128 assert(inherit || decorationStyle != null), 129 assert(inherit || decorationStyle != null),
129 assert(inherit || decorationThickness != null), 130 assert(inherit || decorationThickness != null),
  131 + assert(inherit || renderingMode != null),
130 fontNormal = fontNormal ?? 132 fontNormal = fontNormal ??
131 (fontStyle != FontStyle.italic && fontWeight != FontWeight.bold 133 (fontStyle != FontStyle.italic && fontWeight != FontWeight.bold
132 ? font 134 ? font
@@ -163,6 +165,7 @@ class TextStyle { @@ -163,6 +165,7 @@ class TextStyle {
163 decorationColor: null, 165 decorationColor: null,
164 decorationStyle: TextDecorationStyle.solid, 166 decorationStyle: TextDecorationStyle.solid,
165 decorationThickness: 1, 167 decorationThickness: 1,
  168 + renderingMode: PdfTextRenderingMode.fill,
166 ); 169 );
167 } 170 }
168 171
@@ -210,6 +213,8 @@ class TextStyle { @@ -210,6 +213,8 @@ class TextStyle {
210 213
211 final double decorationThickness; 214 final double decorationThickness;
212 215
  216 + final PdfTextRenderingMode renderingMode;
  217 +
213 TextStyle copyWith({ 218 TextStyle copyWith({
214 PdfColor color, 219 PdfColor color,
215 Font font, 220 Font font,
@@ -229,6 +234,7 @@ class TextStyle { @@ -229,6 +234,7 @@ class TextStyle {
229 PdfColor decorationColor, 234 PdfColor decorationColor,
230 TextDecorationStyle decorationStyle, 235 TextDecorationStyle decorationStyle,
231 double decorationThickness, 236 double decorationThickness,
  237 + PdfTextRenderingMode renderingMode,
232 }) { 238 }) {
233 return TextStyle( 239 return TextStyle(
234 inherit: inherit, 240 inherit: inherit,
@@ -250,6 +256,7 @@ class TextStyle { @@ -250,6 +256,7 @@ class TextStyle {
250 decorationColor: decorationColor ?? this.decorationColor, 256 decorationColor: decorationColor ?? this.decorationColor,
251 decorationStyle: decorationStyle ?? this.decorationStyle, 257 decorationStyle: decorationStyle ?? this.decorationStyle,
252 decorationThickness: decorationThickness ?? this.decorationThickness, 258 decorationThickness: decorationThickness ?? this.decorationThickness,
  259 + renderingMode: renderingMode ?? this.renderingMode,
253 ); 260 );
254 } 261 }
255 262
@@ -342,6 +349,7 @@ class TextStyle { @@ -342,6 +349,7 @@ class TextStyle {
342 decorationColor: other.decorationColor, 349 decorationColor: other.decorationColor,
343 decorationStyle: other.decorationStyle, 350 decorationStyle: other.decorationStyle,
344 decorationThickness: other.decorationThickness, 351 decorationThickness: other.decorationThickness,
  352 + renderingMode: other.renderingMode,
345 ); 353 );
346 } 354 }
347 355
@@ -370,5 +378,5 @@ class TextStyle { @@ -370,5 +378,5 @@ class TextStyle {
370 378
371 @override 379 @override
372 String toString() => 380 String toString() =>
373 - 'TextStyle(color:$color font:$font size:$fontSize weight:$fontWeight style:$fontStyle letterSpacing:$letterSpacing wordSpacing:$wordSpacing lineSpacing:$lineSpacing height:$height background:$background decoration:$decoration decorationColor:$decorationColor decorationStyle:$decorationStyle decorationThickness:$decorationThickness)'; 381 + 'TextStyle(color:$color font:$font size:$fontSize weight:$fontWeight style:$fontStyle letterSpacing:$letterSpacing wordSpacing:$wordSpacing lineSpacing:$lineSpacing height:$height background:$background decoration:$decoration decorationColor:$decorationColor decorationStyle:$decorationStyle decorationThickness:$decorationThickness, renderingMode:$renderingMode)';
374 } 382 }