@trebco/treb 30.16.0 → 31.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/api-generator/api-generator.ts +3 -1
  2. package/api-generator/package.json +2 -1
  3. package/dist/treb-export-worker.mjs +2 -2
  4. package/dist/treb-spreadsheet.mjs +13 -13
  5. package/dist/treb.d.ts +19 -2
  6. package/package.json +8 -7
  7. package/treb-base-types/src/font-stack.ts +144 -0
  8. package/treb-base-types/src/style.ts +121 -11
  9. package/treb-base-types/src/theme.ts +53 -8
  10. package/treb-calculator/src/calculator.ts +13 -13
  11. package/treb-calculator/src/descriptors.ts +12 -4
  12. package/treb-calculator/src/expression-calculator.ts +17 -4
  13. package/treb-calculator/src/functions/base-functions.ts +57 -4
  14. package/treb-calculator/src/functions/statistics-functions.ts +9 -6
  15. package/treb-calculator/tsconfig.json +11 -0
  16. package/treb-charts/style/charts.scss +7 -1
  17. package/treb-data-model/src/annotation.ts +6 -0
  18. package/treb-data-model/src/data_model.ts +14 -3
  19. package/treb-data-model/src/sheet.ts +57 -56
  20. package/treb-embed/markup/toolbar.html +15 -1
  21. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +38 -0
  22. package/treb-embed/src/embedded-spreadsheet.ts +119 -29
  23. package/treb-embed/src/options.ts +3 -0
  24. package/treb-embed/src/selection-state.ts +1 -0
  25. package/treb-embed/src/toolbar-message.ts +6 -0
  26. package/treb-embed/src/types.ts +9 -0
  27. package/treb-embed/style/defaults.scss +12 -1
  28. package/treb-embed/style/font-stacks.scss +105 -0
  29. package/treb-embed/style/layout.scss +1 -0
  30. package/treb-embed/style/theme-defaults.scss +12 -2
  31. package/treb-embed/style/toolbar.scss +16 -0
  32. package/treb-grid/src/editors/overlay_editor.ts +36 -3
  33. package/treb-grid/src/layout/base_layout.ts +52 -37
  34. package/treb-grid/src/layout/grid_layout.ts +7 -0
  35. package/treb-grid/src/render/tile_renderer.ts +154 -148
  36. package/treb-grid/src/types/grid.ts +188 -54
  37. package/treb-grid/src/types/grid_events.ts +1 -1
  38. package/treb-grid/src/types/grid_options.ts +3 -0
  39. package/treb-grid/src/util/fontmetrics.ts +134 -0
  40. package/treb-parser/src/parser.ts +12 -3
  41. package/treb-utils/src/measurement.ts +2 -3
  42. package/tsproject.json +1 -1
  43. package/treb-calculator/modern.tsconfig.json +0 -11
  44. package/treb-grid/src/util/fontmetrics2.ts +0 -182
  45. package/treb-parser/src/parser.test.ts +0 -298
  46. /package/treb-embed/{modern.tsconfig.json → tsconfig.json} +0 -0
  47. /package/treb-export/{modern.tsconfig.json → tsconfig.json} +0 -0
@@ -99,6 +99,13 @@ export class GridLayout extends BaseLayout {
99
99
 
100
100
  }
101
101
 
102
+ public FocusInLayout(target?: EventTarget): boolean {
103
+ if (target && target instanceof Element && this.container?.contains(target)) {
104
+ return true;
105
+ }
106
+ return false;
107
+ }
108
+
102
109
  public ResizeCursor(resize?: 'row'|'column'): void {
103
110
  switch (resize) {
104
111
  case 'row':
@@ -28,16 +28,18 @@ import type { ICellAddress,
28
28
  import { TextPartFlag, Style, ValueType, Area, Rectangle, ResolveThemeColor, IsDefinedColor } from 'treb-base-types';
29
29
 
30
30
  import type { Tile } from '../types/tile';
31
- import { FontMetricsCache as FontMetricsCache2 } from '../util/fontmetrics2';
31
+ // import { FontMetricsCache as FontMetricsCache2 } from '../util/fontmetrics2';
32
32
  import type { FormattedString} from 'treb-parser';
33
33
  import { MDParser } from 'treb-parser';
34
- import type { BaseLayout, TileRange } from '../layout/base_layout';
34
+ import { BaseLayout, TileRange } from '../layout/base_layout';
35
35
  import type { DataModel, ViewModel } from 'treb-data-model';
36
36
  import type { GridOptions } from '../types/grid_options';
37
37
 
38
+ import { Get as GetFontMetrics } from '../util/fontmetrics';
39
+
38
40
  const DEFAULT_INDENT = ' '; // two spaces in the current font
39
- const BASELINE = 'bottom';
40
- const WK = /webkit/i.test(typeof navigator === 'undefined' ? '' : navigator?.userAgent || '') ? 1 : 0;
41
+ // const BASELINE = 'bottom';
42
+ // const WK = /webkit/i.test(typeof navigator === 'undefined' ? '' : navigator?.userAgent || '') ? 1 : 0;
41
43
 
42
44
  interface FontSet {
43
45
  base: string,
@@ -118,7 +120,8 @@ export class TileRenderer {
118
120
  this.buffer_context = context;
119
121
  this.buffer_context.setTransform(scale, 0, 0, scale, 0, 0);
120
122
  this.buffer_context.textAlign = 'left';
121
- this.buffer_context.textBaseline = BASELINE; // 'alphabetic';
123
+ this.buffer_context.textBaseline = // BASELINE; //
124
+ 'alphabetic';
122
125
  }
123
126
 
124
127
  // this.UpdateTheme();
@@ -173,6 +176,52 @@ export class TileRenderer {
173
176
  }
174
177
 
175
178
  /**
179
+ * new method for measuring text, intended to take into account
180
+ * indentation and wrapping, scale, and all the other stuff.
181
+ */
182
+ public MeasureText(cell: Cell, current_width: number, override_scale?: number) {
183
+
184
+ // we need a canvas. I guess we can just randomly use one?
185
+
186
+ const tile = this.layout.grid_tiles[0][0];
187
+
188
+ // we need fonts, and check if we need variants
189
+
190
+ const scale = override_scale ?? this.layout.scale;
191
+ const style: CellStyle = cell.style || {};
192
+ const base_font = Style.CompositeFont(this.theme.grid_cell_font_size, style, scale, this.theme);
193
+ const metrics = GetFontMetrics(base_font.font, base_font.variants);
194
+
195
+ const fonts: FontSet = {
196
+ base: base_font.font,
197
+ strong: Style.CompositeFont(this.theme.grid_cell_font_size, {...style, bold: true}, scale, this.theme).font,
198
+ emphasis: Style.CompositeFont(this.theme.grid_cell_font_size, {...style, italic: true}, scale, this.theme).font,
199
+ strong_emphasis: Style.CompositeFont(this.theme.grid_cell_font_size, {...style, bold: true, italic: true }, scale, this.theme).font,
200
+ };
201
+
202
+ if (base_font.variants) {
203
+ tile.style.fontVariant = base_font.variants;
204
+ }
205
+ else {
206
+ tile.style.fontVariant = '';
207
+ }
208
+
209
+ const context = tile.getContext('2d', { alpha: false });
210
+
211
+ if (!context) {
212
+ throw new Error('context failed');
213
+ }
214
+
215
+ const prepped = this.PrepText(context, fonts, cell, current_width);
216
+
217
+ const width = prepped.width;
218
+ const height = metrics.height * prepped.strings.length;
219
+
220
+ return { width, height };
221
+
222
+ }
223
+
224
+ /* *
176
225
  * use one of the tile contexts to measure text. we are using the tile
177
226
  * context because it's attached to the DOM, and style is applied. we need
178
227
  * that for the root font size, in case font size in the style is relative
@@ -188,7 +237,7 @@ export class TileRenderer {
188
237
  *
189
238
  * @param text
190
239
  * @param font
191
- */
240
+ * /
192
241
  public MeasureText(text: string, font?: string): TextMetrics {
193
242
 
194
243
  const context = this.layout.grid_tiles[0][0].getContext('2d', { alpha: false });
@@ -203,6 +252,7 @@ export class TileRenderer {
203
252
 
204
253
  return context.measureText(text);
205
254
  }
255
+ */
206
256
 
207
257
  /**
208
258
  * when drawing to the buffered canvas, (1) ensure it's large enough,
@@ -233,7 +283,8 @@ export class TileRenderer {
233
283
  if (context) {
234
284
  this.buffer_context = context;
235
285
  this.buffer_context.textAlign = 'left';
236
- this.buffer_context.textBaseline = BASELINE;
286
+ this.buffer_context.textBaseline = // BASELINE;
287
+ 'alphabetic';
237
288
  }
238
289
 
239
290
  }
@@ -291,7 +342,8 @@ export class TileRenderer {
291
342
  throw new Error('invalid context');
292
343
  }
293
344
 
294
- const m2 = FontMetricsCache2.Get(Style.Font(this.theme.headers || {}, this.layout.scale));
345
+ const font_info = Style.CompositeFont(this.theme.grid_cell_font_size, this.theme.headers||{}, this.layout.scale, this.theme);
346
+ const m2 = GetFontMetrics(font_info.font, font_info.variants);
295
347
 
296
348
  const scale = this.layout.dpr;
297
349
  const header_size = this.layout.header_offset;
@@ -351,8 +403,8 @@ export class TileRenderer {
351
403
  // 0 or 1 pixel) we don't want to render them here.
352
404
 
353
405
  context.textAlign = 'center';
354
- context.textBaseline = 'middle';
355
- context.font = Style.Font(this.theme.headers||{}, this.layout.scale);
406
+ context.textBaseline = 'middle'; // FUXME
407
+ context.font = font_info.font; // Style.Font(this.theme.headers||{}, this.layout.scale);
356
408
 
357
409
  context.fillStyle = ResolveThemeColor(this.theme, this.theme.headers?.text);
358
410
 
@@ -365,7 +417,8 @@ export class TileRenderer {
365
417
  context.lineTo(header_size.x, 0 - 0.5);
366
418
  context.stroke();
367
419
 
368
- this.RenderRowLabels(context, 0, this.view.active_sheet.freeze.rows - 1, m2.block);
420
+ this.RenderRowLabels(context, 0, this.view.active_sheet.freeze.rows - 1, // m2.block);
421
+ m2.height);
369
422
 
370
423
  }
371
424
 
@@ -458,7 +511,10 @@ export class TileRenderer {
458
511
 
459
512
  const scale = this.layout.dpr;
460
513
  const header_size = this.layout.header_offset;
461
- const m2 = FontMetricsCache2.Get(Style.Font(this.theme.headers || {}, this.layout.scale));
514
+
515
+ const font_info = Style.CompositeFont(this.theme.grid_cell_font_size, this.theme.headers||{}, this.layout.scale, this.theme);
516
+ const m2 = GetFontMetrics(font_info.font, font_info.variants);
517
+
462
518
 
463
519
  for (let column = tiles.start.column; column <= tiles.end.column; column++) {
464
520
 
@@ -470,8 +526,15 @@ export class TileRenderer {
470
526
  context.setTransform(scale, 0, 0, scale, 0, 0);
471
527
 
472
528
  context.textAlign = 'center';
473
- context.textBaseline = 'middle';
474
- context.font = Style.Font(this.theme.headers||{}, this.layout.scale);
529
+ context.textBaseline = 'middle'; // FIXME
530
+
531
+ context.font = font_info.font; // Style.Font(this.theme.headers||{}, this.layout.scale);
532
+ if (font_info.variants) {
533
+ tile.style.fontVariant = font_info.variants;
534
+ }
535
+ else {
536
+ tile.style.fontVariant = '';
537
+ }
475
538
 
476
539
  context.fillStyle = this.theme.headers?.fill ? ResolveThemeColor(this.theme, this.theme.headers.fill) : '';
477
540
  context.fillRect(0, 0, tile.logical_size.width, this.layout.header_offset.y);
@@ -512,8 +575,16 @@ export class TileRenderer {
512
575
  context.setTransform(scale, 0, 0, scale, 0, 0);
513
576
 
514
577
  context.textAlign = 'center';
515
- context.textBaseline = 'middle';
516
- context.font = Style.Font(this.theme.headers||{}, this.layout.scale);
578
+ context.textBaseline = 'middle'; // FIXME
579
+ // context.font = Style.Font(this.theme.headers||{}, this.layout.scale);
580
+
581
+ context.font = font_info.font; // Style.Font(this.theme.headers||{}, this.layout.scale);
582
+ if (font_info.variants) {
583
+ tile.style.fontVariant = font_info.variants;
584
+ }
585
+ else {
586
+ tile.style.fontVariant = '';
587
+ }
517
588
 
518
589
  context.fillRect(0, 0, this.layout.header_offset.x, tile.logical_size.height);
519
590
 
@@ -527,7 +598,8 @@ export class TileRenderer {
527
598
 
528
599
  context.strokeStyle = this.theme.headers_grid_color || '';
529
600
 
530
- this.RenderRowLabels(context, tile.first_cell.row, tile.last_cell.row, m2.block);
601
+ this.RenderRowLabels(context, tile.first_cell.row, tile.last_cell.row, // m2.block);
602
+ m2.height);
531
603
 
532
604
  tile.dirty = false;
533
605
  }
@@ -587,10 +659,18 @@ export class TileRenderer {
587
659
  /** render a tile */
588
660
  public Render(tile: Tile): void {
589
661
 
662
+ // can we assume this is always set? this feels sloppy, and
663
+ // it feels like something we'd like to turn off... can we
664
+ // fetch the canvas more than once? not sure what the impact of
665
+ // that would be.
666
+
667
+ // tile.style.fontVariantNumeric = 'lining-nums tabular-nums';
668
+
590
669
  const context = tile.getContext('2d', { alpha: false });
591
670
  if (!context) { return; } // should throw
592
671
 
593
- context.textBaseline = BASELINE;
672
+ context.textBaseline = // BASELINE;
673
+ 'alphabetic';
594
674
 
595
675
  const scale = this.layout.dpr;
596
676
 
@@ -1654,13 +1734,28 @@ export class TileRenderer {
1654
1734
  // (eventually) painting to the buffer context. just remember to set
1655
1735
  // font in the buffer context.
1656
1736
 
1737
+ const base_font = Style.CompositeFont(this.theme.grid_cell_font_size, style, this.layout.scale, this.theme);
1738
+
1739
+ /*
1740
+ if (cell.value) {
1741
+ console.info(base_font);
1742
+ }
1743
+ */
1744
+
1657
1745
  const fonts: FontSet = {
1658
- base: Style.Font(style, this.layout.scale),
1659
- strong: Style.Font({...style, bold: true}, this.layout.scale),
1660
- emphasis: Style.Font({...style, italic: true}, this.layout.scale),
1661
- strong_emphasis: Style.Font({...style, bold: true, italic: true}, this.layout.scale),
1746
+ base: base_font.font,
1747
+ strong: Style.CompositeFont(this.theme.grid_cell_font_size, {...style, bold: true}, this.layout.scale, this.theme).font,
1748
+ emphasis: Style.CompositeFont(this.theme.grid_cell_font_size, {...style, italic: true}, this.layout.scale, this.theme).font,
1749
+ strong_emphasis: Style.CompositeFont(this.theme.grid_cell_font_size, {...style, bold: true, italic: true }, this.layout.scale, this.theme).font,
1662
1750
  };
1663
1751
 
1752
+ if (base_font.variants) {
1753
+ tile.style.fontVariant = base_font.variants;
1754
+ }
1755
+ else {
1756
+ tile.style.fontVariant = '';
1757
+ }
1758
+
1664
1759
  context.font = fonts.base;
1665
1760
 
1666
1761
  //
@@ -1927,16 +2022,23 @@ export class TileRenderer {
1927
2022
  // and bold variants). this should be OK because we use it for height, mostly.
1928
2023
  // not sure about invisible text (FIXME)
1929
2024
 
1930
- const m2 = FontMetricsCache2.Get(fonts.base, this.theme.grid_cell?.font_size?.value);
1931
- // console.info("FB", fonts.base, m2);
2025
+ // const m2 = FontMetricsCache2.Get(fonts.base, // this.theme.grid_cell?.font_size?.value);
2026
+ // this.theme.grid_cell_font_size);
2027
+
2028
+
2029
+ const m2 = GetFontMetrics(fonts.base, base_font.variants);
1932
2030
 
2031
+ if (cell.value) {
2032
+ console.info(fonts.base, {m2});
2033
+ }
2034
+
1933
2035
  // set stroke for underline
1934
2036
 
1935
2037
  // FIXME: color here should default to style, not ''. it's working only
1936
2038
  // because our default style happens to be the default color. that applies
1937
2039
  // to text color, background color and border color.
1938
2040
 
1939
- context.lineWidth = 1;
2041
+ context.lineWidth = 1; // 1.5; // FIXME: scale? font scale?
1940
2042
 
1941
2043
  context.strokeStyle = context.fillStyle =
1942
2044
  text_data.format ? text_data.format : ResolveThemeColor(this.theme, style.text, 1);
@@ -1945,11 +2047,12 @@ export class TileRenderer {
1945
2047
 
1946
2048
  let left = this.cell_edge_buffer;
1947
2049
 
1948
- const line_height = 1.25;
2050
+ const line_height = 1; // 1.25;
1949
2051
 
1950
2052
  //const line_count = text_data.single ? 1 : text_data.strings.length;
1951
2053
  const line_count = text_data.strings.length;
1952
- const text_height = (line_count * m2.block * line_height);
2054
+ // const text_height = (line_count * m2.block * line_height);
2055
+ const text_height = (line_count * m2.height * line_height);
1953
2056
 
1954
2057
  // we stopped clipping initially because it was expensive -- but then
1955
2058
  // we were doing it on every cell. it's hard to imagine that clipping
@@ -1970,20 +2073,23 @@ export class TileRenderer {
1970
2073
  context.clip();
1971
2074
  }
1972
2075
 
1973
- // path for underline. if there's no underline, it won't do anything.
2076
+ // path for underline (and strike). if there's no underline (or strike),
2077
+ // it won't do anything.
1974
2078
 
1975
2079
  context.beginPath();
1976
2080
 
1977
- // baseline looks OK, if you account for descenders.
1978
-
1979
- let original_baseline = Math.round(height - 2 - (m2.block * line_height * (line_count - 1)) + WK); // switched baseline to "bottom"
2081
+ let original_baseline = Math.round(
2082
+ (height - m2.descent - 2) + // baseline for first line of text
2083
+ (-line_height * m2.height * (line_count - 1))); // adjust for multiple lines
1980
2084
 
1981
2085
  switch (style.vertical_align) {
1982
- case 'top': // Style.VerticalAlign.Top:
1983
- original_baseline = Math.round(m2.block * line_height) + 1;
2086
+ case 'top':
2087
+ original_baseline = Math.round(2 + m2.ascent);
1984
2088
  break;
1985
- case 'middle': // Style.VerticalAlign.Middle:
1986
- original_baseline = Math.round((height - text_height) / 2 + m2.block * line_height);
2089
+
2090
+ case 'middle':
2091
+ original_baseline = Math.round((height - text_height) / 2 + m2.ascent) - 1.5;
2092
+
1987
2093
  break;
1988
2094
  }
1989
2095
 
@@ -2017,7 +2123,7 @@ export class TileRenderer {
2017
2123
  // may have different formatting.
2018
2124
 
2019
2125
  let baseline = original_baseline;
2020
- let index = 0;
2126
+ // let index = 0;
2021
2127
 
2022
2128
  for (const line of text_data.strings) {
2023
2129
 
@@ -2026,29 +2132,17 @@ export class TileRenderer {
2026
2132
  let line_width = 0;
2027
2133
  for (const part of line) { line_width += part.width; }
2028
2134
 
2029
- if (horizontal_align === 'center' /* Style.HorizontalAlign.Center */ ) {
2135
+ if (horizontal_align === 'center') {
2030
2136
  left = Math.round((width - line_width) / 2);
2031
2137
  }
2032
- else if (horizontal_align === 'right' /* Style.HorizontalAlign.Right */ ) {
2138
+ else if (horizontal_align === 'right') {
2033
2139
  left = width - this.cell_edge_buffer - line_width;
2034
2140
  }
2035
2141
 
2036
- /*
2037
- if (style.font_underline) {
2038
- const underline_y = Math.floor(baseline + 1.5 - m2.descender - WK) + .5; // metrics.block - 3.5 - metrics.ascent - 3;
2039
- context.moveTo(left, underline_y);
2040
- context.lineTo(left + line_width, underline_y);
2041
- }
2042
-
2043
- if (style.font_strike) {
2044
- const strike_y = Math.floor(baseline - m2.descender - m2.ascender / 2) + .5;
2045
- context.moveTo(left, strike_y);
2046
- context.lineTo(left + line_width, strike_y);
2047
- }
2048
- */
2142
+ // still tinkering with these. surely we need to apply scale? FIXME
2049
2143
 
2050
- const underline_y = Math.floor(baseline + 1.5 - m2.descender - WK) + .5; // metrics.block - 3.5 - metrics.ascent - 3;
2051
- const strike_y = Math.floor(baseline - m2.descender - m2.ascender / 2) + .5;
2144
+ const underline_y = baseline + 2.5;
2145
+ const strike_y = Math.floor(baseline - m2.ascent * 1 / 3) + .5;
2052
2146
 
2053
2147
  let x = left;
2054
2148
  for (const part of line) {
@@ -2089,8 +2183,10 @@ export class TileRenderer {
2089
2183
 
2090
2184
  if (preserve_layout_info) {
2091
2185
  part.left = x;
2092
- part.top = baseline - m2.block;
2093
- part.height = m2.block;
2186
+ part.top = baseline - // m2.block;
2187
+ m2.ascent;
2188
+ part.height = // m2.block;
2189
+ m2.height;
2094
2190
  }
2095
2191
 
2096
2192
  }
@@ -2099,106 +2195,16 @@ export class TileRenderer {
2099
2195
 
2100
2196
  }
2101
2197
 
2102
- index++;
2103
- baseline = Math.round(original_baseline + index * m2.block * line_height);
2104
-
2105
- }
2198
+ // height tends to be an integer, or maybe at worst 1/2 integer,
2199
+ // so stepping is probably ok (we used to index and multiply).
2106
2200
 
2201
+ baseline += line_height * m2.height;
2107
2202
 
2108
- }
2109
2203
 
2110
- /*
2111
- else if (text_data.single) {
2112
-
2113
- // const cached_font = context.font;
2114
- // const italic_font = /italic/i.test(cached_font) ? cached_font : 'italic ' + cached_font;
2115
-
2116
- // single refers to single-line text that has multiple components,
2117
- // including spacing or hidden text. single line text (not formatted)
2118
- // probably doesn't have this flag set, it will use the next block.
2119
- // these could (should?) be consolidated
2120
-
2121
- if (horizontal_align === Style.HorizontalAlign.Center) {
2122
- left = Math.round((width - text_data.width) / 2);
2123
- }
2124
- else if (horizontal_align === Style.HorizontalAlign.Right) {
2125
- left = width - this.cell_edge_buffer - text_data.width;
2126
2204
  }
2127
2205
 
2128
- const underline_y = Math.floor(original_baseline + 1.5 - m2.descender - WK) + .5; // metrics.block - 3.5 - metrics.ascent - 3;
2129
- const strike_y = Math.floor(original_baseline - m2.descender - m2.ascender / 2) + .5;
2130
-
2131
- // we want a single underline, possibly spanning hidden elements,
2132
- // but not starting or stopping on a hidden element (usually invisible
2133
- // parentheses).
2134
-
2135
- for (const part of text_data.strings) {
2136
- if (!part.hidden) {
2137
-
2138
- context.fillText(part.text, left, original_baseline);
2139
-
2140
- if (style.font_underline) {
2141
- context.moveTo(left, underline_y);
2142
- context.lineTo(left + part.width, underline_y);
2143
- }
2144
- if (style.font_strike) {
2145
- context.moveTo(left, strike_y);
2146
- context.lineTo(left + part.width, strike_y);
2147
- }
2148
- }
2149
-
2150
- if (preserve_layout_info) {
2151
- part.left = left;
2152
- part.top = original_baseline - m2.block;
2153
- part.height = m2.block;
2154
- }
2155
-
2156
- left += part.width;
2157
- }
2158
-
2159
- }
2160
- else {
2161
-
2162
- let baseline = original_baseline;
2163
- let index = 0;
2164
-
2165
- for (const part of text_data.strings) {
2166
-
2167
- // here we justify based on part, each line might have different width
2168
-
2169
- if (horizontal_align === Style.HorizontalAlign.Center) {
2170
- left = Math.round((width - part.width) / 2);
2171
- }
2172
- else if (horizontal_align === Style.HorizontalAlign.Right) {
2173
- left = width - this.cell_edge_buffer - part.width;
2174
- }
2175
-
2176
- if (style.font_underline) {
2177
- const underline_y = Math.floor(baseline + 1.5 - m2.descender - WK) + .5; // metrics.block - 3.5 - metrics.ascent - 3;
2178
- context.moveTo(left, underline_y);
2179
- context.lineTo(left + part.width, underline_y);
2180
- }
2181
-
2182
- if (style.font_strike) {
2183
- const strike_y = Math.floor(baseline - m2.descender - m2.ascender / 2) + .5;
2184
- context.moveTo(left, strike_y);
2185
- context.lineTo(left + part.width, strike_y);
2186
- }
2187
-
2188
- context.fillText(part.text, left, baseline);
2189
-
2190
- if (preserve_layout_info) {
2191
- part.left = left;
2192
- part.top = baseline - m2.block;
2193
- part.height = m2.block;
2194
- }
2195
-
2196
- index++;
2197
- baseline = Math.round(original_baseline + index * m2.block * line_height);
2198
- }
2199
2206
 
2200
2207
  }
2201
- */
2202
2208
 
2203
2209
  context.stroke();
2204
2210