emf-converter 4.20.1 → 4.20.3
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.
- package/dist/browser.js +141 -25
- package/dist/browser.mjs +141 -25
- package/dist/index.js +141 -25
- package/dist/index.mjs +141 -25
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -29019,7 +29019,7 @@ var MonoStubContour = class {
|
|
|
29019
29019
|
constructor(o) {
|
|
29020
29020
|
this.points = Array.from(o.xs, (x, i) => [x / 64 - 0.5, o.ys[i] / 64 - 0.5]);
|
|
29021
29021
|
}
|
|
29022
|
-
isStub(flipped, scan, crossing, lo, hi, precision) {
|
|
29022
|
+
isStub(flipped, scan, crossing, lo, hi, precision, _opposite) {
|
|
29023
29023
|
const points = this.points;
|
|
29024
29024
|
const n = points.length;
|
|
29025
29025
|
const point = (i) => flipped ? [points[i][1], points[i][0]] : points[i];
|
|
@@ -29055,6 +29055,82 @@ var MonoStubContour = class {
|
|
|
29055
29055
|
return !(a.side * b.side < 0 && a.continues && b.continues);
|
|
29056
29056
|
}
|
|
29057
29057
|
};
|
|
29058
|
+
function convexContour(o) {
|
|
29059
|
+
const edges = [];
|
|
29060
|
+
for (let i = 0; i < o.xs.length; i++) {
|
|
29061
|
+
const j = (i + 1) % o.xs.length;
|
|
29062
|
+
const dx = o.xs[j] - o.xs[i], dy = o.ys[j] - o.ys[i];
|
|
29063
|
+
if (dx || dy) edges.push([dx, dy]);
|
|
29064
|
+
}
|
|
29065
|
+
if (edges.length < 3) return false;
|
|
29066
|
+
const half = (p) => p[1] > 0 || p[1] === 0 && p[0] >= 0 ? 0 : 1;
|
|
29067
|
+
let direction = 0, revolutions = 0;
|
|
29068
|
+
for (let i = 0; i < edges.length; i++) {
|
|
29069
|
+
const a = edges[i], b = edges[(i + 1) % edges.length];
|
|
29070
|
+
const cross = a[0] * b[1] - a[1] * b[0];
|
|
29071
|
+
if (!cross) {
|
|
29072
|
+
if (a[0] * b[0] + a[1] * b[1] < 0) return false;
|
|
29073
|
+
continue;
|
|
29074
|
+
}
|
|
29075
|
+
const turn = Math.sign(cross);
|
|
29076
|
+
if (direction && direction !== turn) return false;
|
|
29077
|
+
direction = turn;
|
|
29078
|
+
if (half(a) !== half(b) && half(a) === (turn > 0 ? 1 : 0)) revolutions++;
|
|
29079
|
+
}
|
|
29080
|
+
return direction !== 0 && revolutions === 1;
|
|
29081
|
+
}
|
|
29082
|
+
var MonoStubContours = class _MonoStubContours {
|
|
29083
|
+
constructor(contours) {
|
|
29084
|
+
this.contours = contours;
|
|
29085
|
+
}
|
|
29086
|
+
static create(o) {
|
|
29087
|
+
if (o.endPts.length > 64) return null;
|
|
29088
|
+
if (Array.from(o.onCurve).some((p) => !p)) return null;
|
|
29089
|
+
if (o.endPts.length === 1) return new MonoStubContour(o);
|
|
29090
|
+
const contours = [];
|
|
29091
|
+
const boxes = [];
|
|
29092
|
+
let start = 0;
|
|
29093
|
+
for (const end of o.endPts) {
|
|
29094
|
+
const xs = [], ys = [], onCurve = [];
|
|
29095
|
+
for (let i = start; i <= end; i++) {
|
|
29096
|
+
xs.push(o.xs[i]);
|
|
29097
|
+
ys.push(o.ys[i]);
|
|
29098
|
+
onCurve.push(o.onCurve[i]);
|
|
29099
|
+
}
|
|
29100
|
+
const part = { xs, ys, onCurve, endPts: [end - start] };
|
|
29101
|
+
start = end + 1;
|
|
29102
|
+
if (!convexContour(part)) return null;
|
|
29103
|
+
const box = { xMin: Infinity, xMax: -Infinity, yMin: Infinity, yMax: -Infinity };
|
|
29104
|
+
for (let i = 0; i < part.xs.length; i++) {
|
|
29105
|
+
box.xMin = Math.min(box.xMin, part.xs[i]);
|
|
29106
|
+
box.xMax = Math.max(box.xMax, part.xs[i]);
|
|
29107
|
+
box.yMin = Math.min(box.yMin, part.ys[i]);
|
|
29108
|
+
box.yMax = Math.max(box.yMax, part.ys[i]);
|
|
29109
|
+
}
|
|
29110
|
+
if (boxes.some((b) => box.xMin <= b.xMax + 64 && b.xMin <= box.xMax + 64 && box.yMin <= b.yMax + 64 && b.yMin <= box.yMax + 64)) return null;
|
|
29111
|
+
boxes.push(box);
|
|
29112
|
+
contours.push(new MonoStubContour(part));
|
|
29113
|
+
}
|
|
29114
|
+
return new _MonoStubContours(contours);
|
|
29115
|
+
}
|
|
29116
|
+
isStub(flipped, scan, crossing, lo, hi, precision, opposite) {
|
|
29117
|
+
let owner = -1, otherOwner = -1, result = null;
|
|
29118
|
+
for (let i = 0; i < this.contours.length; i++) {
|
|
29119
|
+
const a = this.contours[i].isStub(flipped, scan, crossing, lo, hi, precision);
|
|
29120
|
+
const b = this.contours[i].isStub(flipped, scan, opposite, lo, hi, precision);
|
|
29121
|
+
if (a !== null) {
|
|
29122
|
+
if (owner >= 0) return null;
|
|
29123
|
+
owner = i;
|
|
29124
|
+
result = a;
|
|
29125
|
+
}
|
|
29126
|
+
if (b !== null) {
|
|
29127
|
+
if (otherOwner >= 0) return null;
|
|
29128
|
+
otherOwner = i;
|
|
29129
|
+
}
|
|
29130
|
+
}
|
|
29131
|
+
return owner >= 0 && owner === otherOwner ? result : null;
|
|
29132
|
+
}
|
|
29133
|
+
};
|
|
29058
29134
|
function monoBox(o) {
|
|
29059
29135
|
const n = o.xs.length;
|
|
29060
29136
|
if (n === 0) {
|
|
@@ -29076,16 +29152,11 @@ function monoBox(o) {
|
|
|
29076
29152
|
let xMax = Math.floor((cxMax + 32) / 64);
|
|
29077
29153
|
let yMin = Math.floor((cyMin + 31) / 64);
|
|
29078
29154
|
let yMax = Math.floor((cyMax + 32) / 64);
|
|
29079
|
-
const
|
|
29080
|
-
|
|
29081
|
-
|
|
29082
|
-
|
|
29083
|
-
}
|
|
29084
|
-
if (yMin === yMax) {
|
|
29085
|
-
if (rem(cyMin, 31) + rem(cyMax, 32) < 0) yMin -= 1;
|
|
29086
|
-
else yMax += 1;
|
|
29087
|
-
}
|
|
29088
|
-
return { xMin, xMax, yMin, yMax };
|
|
29155
|
+
const collapsedX = xMin === xMax;
|
|
29156
|
+
const collapsedY = yMin === yMax;
|
|
29157
|
+
if (collapsedX) xMax += 1;
|
|
29158
|
+
if (collapsedY) yMax += 1;
|
|
29159
|
+
return { xMin, xMax, yMin, yMax, collapsedX, collapsedY };
|
|
29089
29160
|
}
|
|
29090
29161
|
function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossings26Dot6 = false) {
|
|
29091
29162
|
const box = fixedBox ?? monoBox(o);
|
|
@@ -29109,7 +29180,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29109
29180
|
const at = (col, row2) => (height - 1 - row2) * width + col;
|
|
29110
29181
|
const r = new Raster(dropout);
|
|
29111
29182
|
const P = r.precision;
|
|
29112
|
-
const monoContour = stubOvershoot && (dropout === 1 || dropout === 4 || dropout === 5)
|
|
29183
|
+
const monoContour = stubOvershoot && (dropout === 1 || dropout === 4 || dropout === 5) ? MonoStubContours.create(local) : null;
|
|
29113
29184
|
const smartPixel = (raster, x1, x2) => {
|
|
29114
29185
|
if (monoContour && smartCrossings26Dot6) {
|
|
29115
29186
|
const step = P / 64;
|
|
@@ -29152,7 +29223,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29152
29223
|
break;
|
|
29153
29224
|
case 1:
|
|
29154
29225
|
case 5:
|
|
29155
|
-
const stub = monoContour?.isStub(false, y, x1 / P, e2 / P, e1 / P, P);
|
|
29226
|
+
const stub = monoContour && box.collapsedX ? false : monoContour?.isStub(false, y, x1 / P, e2 / P, e1 / P, P, x2 / P);
|
|
29156
29227
|
if (stub === true) return;
|
|
29157
29228
|
if (stub == null && left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= r.half)) {
|
|
29158
29229
|
return;
|
|
@@ -29213,7 +29284,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29213
29284
|
break;
|
|
29214
29285
|
case 1:
|
|
29215
29286
|
case 5:
|
|
29216
|
-
const stub = monoContour?.isStub(true, col, x1 / P, e2 / P, e1 / P, P);
|
|
29287
|
+
const stub = monoContour && box.collapsedY ? false : monoContour?.isStub(true, col, x1 / P, e2 / P, e1 / P, P, x2 / P);
|
|
29217
29288
|
if (stub === true) return;
|
|
29218
29289
|
if (stub == null && left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= h.half)) {
|
|
29219
29290
|
return;
|
|
@@ -29577,6 +29648,7 @@ var RasterRealizedFont = class {
|
|
|
29577
29648
|
fsSelection: face.italic ? 1 : 0,
|
|
29578
29649
|
macStyle: 0,
|
|
29579
29650
|
winAscent: this.ascent,
|
|
29651
|
+
winDescent: this.descent,
|
|
29580
29652
|
unitsPerEm: this.ppem || 1
|
|
29581
29653
|
};
|
|
29582
29654
|
}
|
|
@@ -29764,6 +29836,11 @@ var RealizedFont = class {
|
|
|
29764
29836
|
}
|
|
29765
29837
|
return base + (this.syntheticBold ? 1 : 0);
|
|
29766
29838
|
}
|
|
29839
|
+
/** GDI+ rounds tracked hmtx advances to font units before device scaling. */
|
|
29840
|
+
designAdvance(index, tracking) {
|
|
29841
|
+
const { advance } = this.ttf.hMetrics(index < this.ttf.numGlyphs ? index : NOTDEF);
|
|
29842
|
+
return Math.round(advance * tracking) * this.ppemX / this.ttf.unitsPerEm + (this.syntheticBold ? 1 : 0);
|
|
29843
|
+
}
|
|
29767
29844
|
/**
|
|
29768
29845
|
* Advance of glyph `index` in a font realised with an escapement: GDI
|
|
29769
29846
|
* does not use the hinted/hdmx widths there but the linearly scaled
|
|
@@ -40451,6 +40528,35 @@ function surfaceSize5(ctx) {
|
|
|
40451
40528
|
return typeof w === "number" && typeof h === "number" && w > 0 && h > 0 ? { w, h } : null;
|
|
40452
40529
|
}
|
|
40453
40530
|
|
|
40531
|
+
// src/emf-plus-text-alignment.ts
|
|
40532
|
+
var SIMPLE_SCRIPT = /^(?:\p{Script=Latin}|\p{Script=Common}|\p{Co})$/u;
|
|
40533
|
+
var SHAPING_CHARACTER = /[\p{M}\p{Cf}\p{Emoji_Presentation}]/u;
|
|
40534
|
+
function layoutPlusAlignedString(font, codes, format, x, y, width, height) {
|
|
40535
|
+
const horizontal = format.alignment, vertical = format.lineAlignment;
|
|
40536
|
+
if (!horizontal && !vertical || horizontal < 0 || horizontal > 2 || vertical < 0 || vertical > 2 || font.gridFit || font.mode !== "gray" || !font.designAdvance || font.ttf.winDescent === void 0 || font.syntheticBold || font.syntheticItalic || format.flags & 3 || ![x, y, width, height].every(Number.isFinite) || width <= 0 || height <= 0 || codes.some((c) => !Number.isInteger(c) || c < 32 || c > 1114111 || c >= 127 && c <= 159 || c === 8232 || c === 8233)) return null;
|
|
40537
|
+
if (codes.some((c) => {
|
|
40538
|
+
const character = String.fromCodePoint(c);
|
|
40539
|
+
return !SIMPLE_SCRIPT.test(character) || SHAPING_CHARACTER.test(character) || font.glyphIndex(c) === 0;
|
|
40540
|
+
})) return null;
|
|
40541
|
+
const em = font.ppem;
|
|
40542
|
+
const tracking = format.tracking ?? 1.03;
|
|
40543
|
+
const leading = em * (format.leadingMargin ?? 1 / 6);
|
|
40544
|
+
const trailing = em * (format.trailingMargin ?? 1 / 6);
|
|
40545
|
+
if (![tracking, leading, trailing].every((v) => Number.isFinite(v) && v >= 0)) return null;
|
|
40546
|
+
if (!(format.flags & 4) && (font.ttf.fsSelection & 1 || font.ttf.macStyle & 2)) return null;
|
|
40547
|
+
const dx = codes.map((c) => font.designAdvance(font.glyphIndex(c), tracking));
|
|
40548
|
+
let measuredCount = codes.length;
|
|
40549
|
+
if (!(format.flags & 2048)) while (measuredCount > 0 && codes[measuredCount - 1] === 32) measuredCount--;
|
|
40550
|
+
const measuredWidth = dx.slice(0, measuredCount).reduce((a, b) => a + b, 0) + leading + trailing;
|
|
40551
|
+
const measuredHeight = em * (font.ttf.winAscent + font.ttf.winDescent) / font.ttf.unitsPerEm + (format.flags & 4 ? 0 : em / 8);
|
|
40552
|
+
if (measuredWidth > width || measuredHeight > height) return null;
|
|
40553
|
+
return {
|
|
40554
|
+
x: Math.fround(x + horizontal / 2 * (width - measuredWidth) + leading),
|
|
40555
|
+
y: Math.fround(y + vertical / 2 * (height - measuredHeight)) + Math.round(em * font.ttf.winAscent / font.ttf.unitsPerEm),
|
|
40556
|
+
dx
|
|
40557
|
+
};
|
|
40558
|
+
}
|
|
40559
|
+
|
|
40454
40560
|
// src/emf-plus-text-image-handlers.ts
|
|
40455
40561
|
function imageAttributesWrap(rCtx, attributesId) {
|
|
40456
40562
|
const obj = attributesId <= 255 ? rCtx.objectTable.get(attributesId) : void 0;
|
|
@@ -40719,25 +40825,33 @@ function paintPlusEngineRun(rCtx, ef, run) {
|
|
|
40719
40825
|
);
|
|
40720
40826
|
return true;
|
|
40721
40827
|
}
|
|
40722
|
-
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, alignment, format, brushSampler2 = null) {
|
|
40723
|
-
if (alignment !== 0) {
|
|
40724
|
-
return false;
|
|
40725
|
-
}
|
|
40828
|
+
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, layoutW, layoutH, paint, alignment, format, brushSampler2 = null) {
|
|
40726
40829
|
const ef = realizePlusEngineFont(rCtx, font, paint, brushSampler2);
|
|
40727
40830
|
if (!ef) {
|
|
40728
40831
|
return false;
|
|
40729
40832
|
}
|
|
40730
40833
|
const { realized, emPx, m, unhinted } = ef;
|
|
40834
|
+
const codes = Array.from(text, (character) => character.codePointAt(0));
|
|
40835
|
+
if (format && (alignment !== 0 || format.lineAlignment !== 0) && unhinted && m[0] === m[3] && Math.fround(emPx) === realized.ppem) {
|
|
40836
|
+
const aligned = layoutPlusAlignedString(
|
|
40837
|
+
realized,
|
|
40838
|
+
codes,
|
|
40839
|
+
format,
|
|
40840
|
+
m[0] * layoutX + m[4],
|
|
40841
|
+
m[3] * layoutY + m[5],
|
|
40842
|
+
m[0] * layoutW,
|
|
40843
|
+
m[3] * layoutH
|
|
40844
|
+
);
|
|
40845
|
+
if (aligned) return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, ...aligned, dy: null });
|
|
40846
|
+
}
|
|
40847
|
+
if (alignment !== 0) return false;
|
|
40731
40848
|
const ttf = realized.ttf;
|
|
40732
40849
|
const exactAscent = emPx * ttf.winAscent / ttf.unitsPerEm;
|
|
40733
|
-
const
|
|
40850
|
+
const clearTypeCell = realized.mode === "cleartype" && !realized.syntheticBold && !realized.syntheticItalic && emPx === realized.ppem && m[0] === 1 && m[3] === 1 && Number.isInteger(layoutY + m[5]) && (format?.lineAlignment ?? 0) === 0;
|
|
40851
|
+
const ascent = unhinted ? Math.round(exactAscent) : clearTypeCell ? Math.max(Math.round(exactAscent), realized.ascent) : Math.ceil(exactAscent);
|
|
40734
40852
|
let x = m[0] * layoutX + m[4] + emPx * (format?.leadingMargin ?? PLUS_LEADING_EM);
|
|
40735
40853
|
if (!unhinted) x = Math.round(x);
|
|
40736
40854
|
const y = m[3] * layoutY + m[5] + ascent;
|
|
40737
|
-
const codes = [];
|
|
40738
|
-
for (const character of text) {
|
|
40739
|
-
codes.push(character.codePointAt(0));
|
|
40740
|
-
}
|
|
40741
40855
|
const tracking = format?.tracking ?? PLUS_DEFAULT_TRACKING;
|
|
40742
40856
|
const dx = unhinted ? codes.map((c) => realized.advance(realized.glyphIndex(c)) * tracking) : null;
|
|
40743
40857
|
return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, x, y, dx, dy: null });
|
|
@@ -40819,8 +40933,8 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
40819
40933
|
const strLen = view.getUint32(dataOff + 8, true);
|
|
40820
40934
|
const layoutX = view.getFloat32(dataOff + 12, true);
|
|
40821
40935
|
const layoutY = view.getFloat32(dataOff + 16, true);
|
|
40822
|
-
view.getFloat32(dataOff + 20, true);
|
|
40823
|
-
view.getFloat32(dataOff + 24, true);
|
|
40936
|
+
const layoutW = view.getFloat32(dataOff + 20, true);
|
|
40937
|
+
const layoutH = view.getFloat32(dataOff + 24, true);
|
|
40824
40938
|
const fontId = recFlags & 255;
|
|
40825
40939
|
const font = objectTable.get(fontId);
|
|
40826
40940
|
if (strLen > 0 && dataOff + 28 + strLen * 2 <= dataOff + recDataSize) {
|
|
@@ -40836,6 +40950,8 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
40836
40950
|
text,
|
|
40837
40951
|
layoutX,
|
|
40838
40952
|
layoutY,
|
|
40953
|
+
layoutW,
|
|
40954
|
+
layoutH,
|
|
40839
40955
|
paint,
|
|
40840
40956
|
alignment,
|
|
40841
40957
|
format,
|
package/dist/browser.mjs
CHANGED
|
@@ -29017,7 +29017,7 @@ var MonoStubContour = class {
|
|
|
29017
29017
|
constructor(o) {
|
|
29018
29018
|
this.points = Array.from(o.xs, (x, i) => [x / 64 - 0.5, o.ys[i] / 64 - 0.5]);
|
|
29019
29019
|
}
|
|
29020
|
-
isStub(flipped, scan, crossing, lo, hi, precision) {
|
|
29020
|
+
isStub(flipped, scan, crossing, lo, hi, precision, _opposite) {
|
|
29021
29021
|
const points = this.points;
|
|
29022
29022
|
const n = points.length;
|
|
29023
29023
|
const point = (i) => flipped ? [points[i][1], points[i][0]] : points[i];
|
|
@@ -29053,6 +29053,82 @@ var MonoStubContour = class {
|
|
|
29053
29053
|
return !(a.side * b.side < 0 && a.continues && b.continues);
|
|
29054
29054
|
}
|
|
29055
29055
|
};
|
|
29056
|
+
function convexContour(o) {
|
|
29057
|
+
const edges = [];
|
|
29058
|
+
for (let i = 0; i < o.xs.length; i++) {
|
|
29059
|
+
const j = (i + 1) % o.xs.length;
|
|
29060
|
+
const dx = o.xs[j] - o.xs[i], dy = o.ys[j] - o.ys[i];
|
|
29061
|
+
if (dx || dy) edges.push([dx, dy]);
|
|
29062
|
+
}
|
|
29063
|
+
if (edges.length < 3) return false;
|
|
29064
|
+
const half = (p) => p[1] > 0 || p[1] === 0 && p[0] >= 0 ? 0 : 1;
|
|
29065
|
+
let direction = 0, revolutions = 0;
|
|
29066
|
+
for (let i = 0; i < edges.length; i++) {
|
|
29067
|
+
const a = edges[i], b = edges[(i + 1) % edges.length];
|
|
29068
|
+
const cross = a[0] * b[1] - a[1] * b[0];
|
|
29069
|
+
if (!cross) {
|
|
29070
|
+
if (a[0] * b[0] + a[1] * b[1] < 0) return false;
|
|
29071
|
+
continue;
|
|
29072
|
+
}
|
|
29073
|
+
const turn = Math.sign(cross);
|
|
29074
|
+
if (direction && direction !== turn) return false;
|
|
29075
|
+
direction = turn;
|
|
29076
|
+
if (half(a) !== half(b) && half(a) === (turn > 0 ? 1 : 0)) revolutions++;
|
|
29077
|
+
}
|
|
29078
|
+
return direction !== 0 && revolutions === 1;
|
|
29079
|
+
}
|
|
29080
|
+
var MonoStubContours = class _MonoStubContours {
|
|
29081
|
+
constructor(contours) {
|
|
29082
|
+
this.contours = contours;
|
|
29083
|
+
}
|
|
29084
|
+
static create(o) {
|
|
29085
|
+
if (o.endPts.length > 64) return null;
|
|
29086
|
+
if (Array.from(o.onCurve).some((p) => !p)) return null;
|
|
29087
|
+
if (o.endPts.length === 1) return new MonoStubContour(o);
|
|
29088
|
+
const contours = [];
|
|
29089
|
+
const boxes = [];
|
|
29090
|
+
let start = 0;
|
|
29091
|
+
for (const end of o.endPts) {
|
|
29092
|
+
const xs = [], ys = [], onCurve = [];
|
|
29093
|
+
for (let i = start; i <= end; i++) {
|
|
29094
|
+
xs.push(o.xs[i]);
|
|
29095
|
+
ys.push(o.ys[i]);
|
|
29096
|
+
onCurve.push(o.onCurve[i]);
|
|
29097
|
+
}
|
|
29098
|
+
const part = { xs, ys, onCurve, endPts: [end - start] };
|
|
29099
|
+
start = end + 1;
|
|
29100
|
+
if (!convexContour(part)) return null;
|
|
29101
|
+
const box = { xMin: Infinity, xMax: -Infinity, yMin: Infinity, yMax: -Infinity };
|
|
29102
|
+
for (let i = 0; i < part.xs.length; i++) {
|
|
29103
|
+
box.xMin = Math.min(box.xMin, part.xs[i]);
|
|
29104
|
+
box.xMax = Math.max(box.xMax, part.xs[i]);
|
|
29105
|
+
box.yMin = Math.min(box.yMin, part.ys[i]);
|
|
29106
|
+
box.yMax = Math.max(box.yMax, part.ys[i]);
|
|
29107
|
+
}
|
|
29108
|
+
if (boxes.some((b) => box.xMin <= b.xMax + 64 && b.xMin <= box.xMax + 64 && box.yMin <= b.yMax + 64 && b.yMin <= box.yMax + 64)) return null;
|
|
29109
|
+
boxes.push(box);
|
|
29110
|
+
contours.push(new MonoStubContour(part));
|
|
29111
|
+
}
|
|
29112
|
+
return new _MonoStubContours(contours);
|
|
29113
|
+
}
|
|
29114
|
+
isStub(flipped, scan, crossing, lo, hi, precision, opposite) {
|
|
29115
|
+
let owner = -1, otherOwner = -1, result = null;
|
|
29116
|
+
for (let i = 0; i < this.contours.length; i++) {
|
|
29117
|
+
const a = this.contours[i].isStub(flipped, scan, crossing, lo, hi, precision);
|
|
29118
|
+
const b = this.contours[i].isStub(flipped, scan, opposite, lo, hi, precision);
|
|
29119
|
+
if (a !== null) {
|
|
29120
|
+
if (owner >= 0) return null;
|
|
29121
|
+
owner = i;
|
|
29122
|
+
result = a;
|
|
29123
|
+
}
|
|
29124
|
+
if (b !== null) {
|
|
29125
|
+
if (otherOwner >= 0) return null;
|
|
29126
|
+
otherOwner = i;
|
|
29127
|
+
}
|
|
29128
|
+
}
|
|
29129
|
+
return owner >= 0 && owner === otherOwner ? result : null;
|
|
29130
|
+
}
|
|
29131
|
+
};
|
|
29056
29132
|
function monoBox(o) {
|
|
29057
29133
|
const n = o.xs.length;
|
|
29058
29134
|
if (n === 0) {
|
|
@@ -29074,16 +29150,11 @@ function monoBox(o) {
|
|
|
29074
29150
|
let xMax = Math.floor((cxMax + 32) / 64);
|
|
29075
29151
|
let yMin = Math.floor((cyMin + 31) / 64);
|
|
29076
29152
|
let yMax = Math.floor((cyMax + 32) / 64);
|
|
29077
|
-
const
|
|
29078
|
-
|
|
29079
|
-
|
|
29080
|
-
|
|
29081
|
-
}
|
|
29082
|
-
if (yMin === yMax) {
|
|
29083
|
-
if (rem(cyMin, 31) + rem(cyMax, 32) < 0) yMin -= 1;
|
|
29084
|
-
else yMax += 1;
|
|
29085
|
-
}
|
|
29086
|
-
return { xMin, xMax, yMin, yMax };
|
|
29153
|
+
const collapsedX = xMin === xMax;
|
|
29154
|
+
const collapsedY = yMin === yMax;
|
|
29155
|
+
if (collapsedX) xMax += 1;
|
|
29156
|
+
if (collapsedY) yMax += 1;
|
|
29157
|
+
return { xMin, xMax, yMin, yMax, collapsedX, collapsedY };
|
|
29087
29158
|
}
|
|
29088
29159
|
function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossings26Dot6 = false) {
|
|
29089
29160
|
const box = fixedBox ?? monoBox(o);
|
|
@@ -29107,7 +29178,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29107
29178
|
const at = (col, row2) => (height - 1 - row2) * width + col;
|
|
29108
29179
|
const r = new Raster(dropout);
|
|
29109
29180
|
const P = r.precision;
|
|
29110
|
-
const monoContour = stubOvershoot && (dropout === 1 || dropout === 4 || dropout === 5)
|
|
29181
|
+
const monoContour = stubOvershoot && (dropout === 1 || dropout === 4 || dropout === 5) ? MonoStubContours.create(local) : null;
|
|
29111
29182
|
const smartPixel = (raster, x1, x2) => {
|
|
29112
29183
|
if (monoContour && smartCrossings26Dot6) {
|
|
29113
29184
|
const step = P / 64;
|
|
@@ -29150,7 +29221,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29150
29221
|
break;
|
|
29151
29222
|
case 1:
|
|
29152
29223
|
case 5:
|
|
29153
|
-
const stub = monoContour?.isStub(false, y, x1 / P, e2 / P, e1 / P, P);
|
|
29224
|
+
const stub = monoContour && box.collapsedX ? false : monoContour?.isStub(false, y, x1 / P, e2 / P, e1 / P, P, x2 / P);
|
|
29154
29225
|
if (stub === true) return;
|
|
29155
29226
|
if (stub == null && left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= r.half)) {
|
|
29156
29227
|
return;
|
|
@@ -29211,7 +29282,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29211
29282
|
break;
|
|
29212
29283
|
case 1:
|
|
29213
29284
|
case 5:
|
|
29214
|
-
const stub = monoContour?.isStub(true, col, x1 / P, e2 / P, e1 / P, P);
|
|
29285
|
+
const stub = monoContour && box.collapsedY ? false : monoContour?.isStub(true, col, x1 / P, e2 / P, e1 / P, P, x2 / P);
|
|
29215
29286
|
if (stub === true) return;
|
|
29216
29287
|
if (stub == null && left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= h.half)) {
|
|
29217
29288
|
return;
|
|
@@ -29575,6 +29646,7 @@ var RasterRealizedFont = class {
|
|
|
29575
29646
|
fsSelection: face.italic ? 1 : 0,
|
|
29576
29647
|
macStyle: 0,
|
|
29577
29648
|
winAscent: this.ascent,
|
|
29649
|
+
winDescent: this.descent,
|
|
29578
29650
|
unitsPerEm: this.ppem || 1
|
|
29579
29651
|
};
|
|
29580
29652
|
}
|
|
@@ -29762,6 +29834,11 @@ var RealizedFont = class {
|
|
|
29762
29834
|
}
|
|
29763
29835
|
return base + (this.syntheticBold ? 1 : 0);
|
|
29764
29836
|
}
|
|
29837
|
+
/** GDI+ rounds tracked hmtx advances to font units before device scaling. */
|
|
29838
|
+
designAdvance(index, tracking) {
|
|
29839
|
+
const { advance } = this.ttf.hMetrics(index < this.ttf.numGlyphs ? index : NOTDEF);
|
|
29840
|
+
return Math.round(advance * tracking) * this.ppemX / this.ttf.unitsPerEm + (this.syntheticBold ? 1 : 0);
|
|
29841
|
+
}
|
|
29765
29842
|
/**
|
|
29766
29843
|
* Advance of glyph `index` in a font realised with an escapement: GDI
|
|
29767
29844
|
* does not use the hinted/hdmx widths there but the linearly scaled
|
|
@@ -40449,6 +40526,35 @@ function surfaceSize5(ctx) {
|
|
|
40449
40526
|
return typeof w === "number" && typeof h === "number" && w > 0 && h > 0 ? { w, h } : null;
|
|
40450
40527
|
}
|
|
40451
40528
|
|
|
40529
|
+
// src/emf-plus-text-alignment.ts
|
|
40530
|
+
var SIMPLE_SCRIPT = /^(?:\p{Script=Latin}|\p{Script=Common}|\p{Co})$/u;
|
|
40531
|
+
var SHAPING_CHARACTER = /[\p{M}\p{Cf}\p{Emoji_Presentation}]/u;
|
|
40532
|
+
function layoutPlusAlignedString(font, codes, format, x, y, width, height) {
|
|
40533
|
+
const horizontal = format.alignment, vertical = format.lineAlignment;
|
|
40534
|
+
if (!horizontal && !vertical || horizontal < 0 || horizontal > 2 || vertical < 0 || vertical > 2 || font.gridFit || font.mode !== "gray" || !font.designAdvance || font.ttf.winDescent === void 0 || font.syntheticBold || font.syntheticItalic || format.flags & 3 || ![x, y, width, height].every(Number.isFinite) || width <= 0 || height <= 0 || codes.some((c) => !Number.isInteger(c) || c < 32 || c > 1114111 || c >= 127 && c <= 159 || c === 8232 || c === 8233)) return null;
|
|
40535
|
+
if (codes.some((c) => {
|
|
40536
|
+
const character = String.fromCodePoint(c);
|
|
40537
|
+
return !SIMPLE_SCRIPT.test(character) || SHAPING_CHARACTER.test(character) || font.glyphIndex(c) === 0;
|
|
40538
|
+
})) return null;
|
|
40539
|
+
const em = font.ppem;
|
|
40540
|
+
const tracking = format.tracking ?? 1.03;
|
|
40541
|
+
const leading = em * (format.leadingMargin ?? 1 / 6);
|
|
40542
|
+
const trailing = em * (format.trailingMargin ?? 1 / 6);
|
|
40543
|
+
if (![tracking, leading, trailing].every((v) => Number.isFinite(v) && v >= 0)) return null;
|
|
40544
|
+
if (!(format.flags & 4) && (font.ttf.fsSelection & 1 || font.ttf.macStyle & 2)) return null;
|
|
40545
|
+
const dx = codes.map((c) => font.designAdvance(font.glyphIndex(c), tracking));
|
|
40546
|
+
let measuredCount = codes.length;
|
|
40547
|
+
if (!(format.flags & 2048)) while (measuredCount > 0 && codes[measuredCount - 1] === 32) measuredCount--;
|
|
40548
|
+
const measuredWidth = dx.slice(0, measuredCount).reduce((a, b) => a + b, 0) + leading + trailing;
|
|
40549
|
+
const measuredHeight = em * (font.ttf.winAscent + font.ttf.winDescent) / font.ttf.unitsPerEm + (format.flags & 4 ? 0 : em / 8);
|
|
40550
|
+
if (measuredWidth > width || measuredHeight > height) return null;
|
|
40551
|
+
return {
|
|
40552
|
+
x: Math.fround(x + horizontal / 2 * (width - measuredWidth) + leading),
|
|
40553
|
+
y: Math.fround(y + vertical / 2 * (height - measuredHeight)) + Math.round(em * font.ttf.winAscent / font.ttf.unitsPerEm),
|
|
40554
|
+
dx
|
|
40555
|
+
};
|
|
40556
|
+
}
|
|
40557
|
+
|
|
40452
40558
|
// src/emf-plus-text-image-handlers.ts
|
|
40453
40559
|
function imageAttributesWrap(rCtx, attributesId) {
|
|
40454
40560
|
const obj = attributesId <= 255 ? rCtx.objectTable.get(attributesId) : void 0;
|
|
@@ -40717,25 +40823,33 @@ function paintPlusEngineRun(rCtx, ef, run) {
|
|
|
40717
40823
|
);
|
|
40718
40824
|
return true;
|
|
40719
40825
|
}
|
|
40720
|
-
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, alignment, format, brushSampler2 = null) {
|
|
40721
|
-
if (alignment !== 0) {
|
|
40722
|
-
return false;
|
|
40723
|
-
}
|
|
40826
|
+
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, layoutW, layoutH, paint, alignment, format, brushSampler2 = null) {
|
|
40724
40827
|
const ef = realizePlusEngineFont(rCtx, font, paint, brushSampler2);
|
|
40725
40828
|
if (!ef) {
|
|
40726
40829
|
return false;
|
|
40727
40830
|
}
|
|
40728
40831
|
const { realized, emPx, m, unhinted } = ef;
|
|
40832
|
+
const codes = Array.from(text, (character) => character.codePointAt(0));
|
|
40833
|
+
if (format && (alignment !== 0 || format.lineAlignment !== 0) && unhinted && m[0] === m[3] && Math.fround(emPx) === realized.ppem) {
|
|
40834
|
+
const aligned = layoutPlusAlignedString(
|
|
40835
|
+
realized,
|
|
40836
|
+
codes,
|
|
40837
|
+
format,
|
|
40838
|
+
m[0] * layoutX + m[4],
|
|
40839
|
+
m[3] * layoutY + m[5],
|
|
40840
|
+
m[0] * layoutW,
|
|
40841
|
+
m[3] * layoutH
|
|
40842
|
+
);
|
|
40843
|
+
if (aligned) return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, ...aligned, dy: null });
|
|
40844
|
+
}
|
|
40845
|
+
if (alignment !== 0) return false;
|
|
40729
40846
|
const ttf = realized.ttf;
|
|
40730
40847
|
const exactAscent = emPx * ttf.winAscent / ttf.unitsPerEm;
|
|
40731
|
-
const
|
|
40848
|
+
const clearTypeCell = realized.mode === "cleartype" && !realized.syntheticBold && !realized.syntheticItalic && emPx === realized.ppem && m[0] === 1 && m[3] === 1 && Number.isInteger(layoutY + m[5]) && (format?.lineAlignment ?? 0) === 0;
|
|
40849
|
+
const ascent = unhinted ? Math.round(exactAscent) : clearTypeCell ? Math.max(Math.round(exactAscent), realized.ascent) : Math.ceil(exactAscent);
|
|
40732
40850
|
let x = m[0] * layoutX + m[4] + emPx * (format?.leadingMargin ?? PLUS_LEADING_EM);
|
|
40733
40851
|
if (!unhinted) x = Math.round(x);
|
|
40734
40852
|
const y = m[3] * layoutY + m[5] + ascent;
|
|
40735
|
-
const codes = [];
|
|
40736
|
-
for (const character of text) {
|
|
40737
|
-
codes.push(character.codePointAt(0));
|
|
40738
|
-
}
|
|
40739
40853
|
const tracking = format?.tracking ?? PLUS_DEFAULT_TRACKING;
|
|
40740
40854
|
const dx = unhinted ? codes.map((c) => realized.advance(realized.glyphIndex(c)) * tracking) : null;
|
|
40741
40855
|
return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, x, y, dx, dy: null });
|
|
@@ -40817,8 +40931,8 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
40817
40931
|
const strLen = view.getUint32(dataOff + 8, true);
|
|
40818
40932
|
const layoutX = view.getFloat32(dataOff + 12, true);
|
|
40819
40933
|
const layoutY = view.getFloat32(dataOff + 16, true);
|
|
40820
|
-
view.getFloat32(dataOff + 20, true);
|
|
40821
|
-
view.getFloat32(dataOff + 24, true);
|
|
40934
|
+
const layoutW = view.getFloat32(dataOff + 20, true);
|
|
40935
|
+
const layoutH = view.getFloat32(dataOff + 24, true);
|
|
40822
40936
|
const fontId = recFlags & 255;
|
|
40823
40937
|
const font = objectTable.get(fontId);
|
|
40824
40938
|
if (strLen > 0 && dataOff + 28 + strLen * 2 <= dataOff + recDataSize) {
|
|
@@ -40834,6 +40948,8 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
40834
40948
|
text,
|
|
40835
40949
|
layoutX,
|
|
40836
40950
|
layoutY,
|
|
40951
|
+
layoutW,
|
|
40952
|
+
layoutH,
|
|
40837
40953
|
paint,
|
|
40838
40954
|
alignment,
|
|
40839
40955
|
format,
|
package/dist/index.js
CHANGED
|
@@ -29020,7 +29020,7 @@ var MonoStubContour = class {
|
|
|
29020
29020
|
constructor(o) {
|
|
29021
29021
|
this.points = Array.from(o.xs, (x, i) => [x / 64 - 0.5, o.ys[i] / 64 - 0.5]);
|
|
29022
29022
|
}
|
|
29023
|
-
isStub(flipped, scan, crossing, lo, hi, precision) {
|
|
29023
|
+
isStub(flipped, scan, crossing, lo, hi, precision, _opposite) {
|
|
29024
29024
|
const points = this.points;
|
|
29025
29025
|
const n = points.length;
|
|
29026
29026
|
const point = (i) => flipped ? [points[i][1], points[i][0]] : points[i];
|
|
@@ -29056,6 +29056,82 @@ var MonoStubContour = class {
|
|
|
29056
29056
|
return !(a.side * b.side < 0 && a.continues && b.continues);
|
|
29057
29057
|
}
|
|
29058
29058
|
};
|
|
29059
|
+
function convexContour(o) {
|
|
29060
|
+
const edges = [];
|
|
29061
|
+
for (let i = 0; i < o.xs.length; i++) {
|
|
29062
|
+
const j = (i + 1) % o.xs.length;
|
|
29063
|
+
const dx = o.xs[j] - o.xs[i], dy = o.ys[j] - o.ys[i];
|
|
29064
|
+
if (dx || dy) edges.push([dx, dy]);
|
|
29065
|
+
}
|
|
29066
|
+
if (edges.length < 3) return false;
|
|
29067
|
+
const half = (p) => p[1] > 0 || p[1] === 0 && p[0] >= 0 ? 0 : 1;
|
|
29068
|
+
let direction = 0, revolutions = 0;
|
|
29069
|
+
for (let i = 0; i < edges.length; i++) {
|
|
29070
|
+
const a = edges[i], b = edges[(i + 1) % edges.length];
|
|
29071
|
+
const cross = a[0] * b[1] - a[1] * b[0];
|
|
29072
|
+
if (!cross) {
|
|
29073
|
+
if (a[0] * b[0] + a[1] * b[1] < 0) return false;
|
|
29074
|
+
continue;
|
|
29075
|
+
}
|
|
29076
|
+
const turn = Math.sign(cross);
|
|
29077
|
+
if (direction && direction !== turn) return false;
|
|
29078
|
+
direction = turn;
|
|
29079
|
+
if (half(a) !== half(b) && half(a) === (turn > 0 ? 1 : 0)) revolutions++;
|
|
29080
|
+
}
|
|
29081
|
+
return direction !== 0 && revolutions === 1;
|
|
29082
|
+
}
|
|
29083
|
+
var MonoStubContours = class _MonoStubContours {
|
|
29084
|
+
constructor(contours) {
|
|
29085
|
+
this.contours = contours;
|
|
29086
|
+
}
|
|
29087
|
+
static create(o) {
|
|
29088
|
+
if (o.endPts.length > 64) return null;
|
|
29089
|
+
if (Array.from(o.onCurve).some((p) => !p)) return null;
|
|
29090
|
+
if (o.endPts.length === 1) return new MonoStubContour(o);
|
|
29091
|
+
const contours = [];
|
|
29092
|
+
const boxes = [];
|
|
29093
|
+
let start = 0;
|
|
29094
|
+
for (const end of o.endPts) {
|
|
29095
|
+
const xs = [], ys = [], onCurve = [];
|
|
29096
|
+
for (let i = start; i <= end; i++) {
|
|
29097
|
+
xs.push(o.xs[i]);
|
|
29098
|
+
ys.push(o.ys[i]);
|
|
29099
|
+
onCurve.push(o.onCurve[i]);
|
|
29100
|
+
}
|
|
29101
|
+
const part = { xs, ys, onCurve, endPts: [end - start] };
|
|
29102
|
+
start = end + 1;
|
|
29103
|
+
if (!convexContour(part)) return null;
|
|
29104
|
+
const box = { xMin: Infinity, xMax: -Infinity, yMin: Infinity, yMax: -Infinity };
|
|
29105
|
+
for (let i = 0; i < part.xs.length; i++) {
|
|
29106
|
+
box.xMin = Math.min(box.xMin, part.xs[i]);
|
|
29107
|
+
box.xMax = Math.max(box.xMax, part.xs[i]);
|
|
29108
|
+
box.yMin = Math.min(box.yMin, part.ys[i]);
|
|
29109
|
+
box.yMax = Math.max(box.yMax, part.ys[i]);
|
|
29110
|
+
}
|
|
29111
|
+
if (boxes.some((b) => box.xMin <= b.xMax + 64 && b.xMin <= box.xMax + 64 && box.yMin <= b.yMax + 64 && b.yMin <= box.yMax + 64)) return null;
|
|
29112
|
+
boxes.push(box);
|
|
29113
|
+
contours.push(new MonoStubContour(part));
|
|
29114
|
+
}
|
|
29115
|
+
return new _MonoStubContours(contours);
|
|
29116
|
+
}
|
|
29117
|
+
isStub(flipped, scan, crossing, lo, hi, precision, opposite) {
|
|
29118
|
+
let owner = -1, otherOwner = -1, result = null;
|
|
29119
|
+
for (let i = 0; i < this.contours.length; i++) {
|
|
29120
|
+
const a = this.contours[i].isStub(flipped, scan, crossing, lo, hi, precision);
|
|
29121
|
+
const b = this.contours[i].isStub(flipped, scan, opposite, lo, hi, precision);
|
|
29122
|
+
if (a !== null) {
|
|
29123
|
+
if (owner >= 0) return null;
|
|
29124
|
+
owner = i;
|
|
29125
|
+
result = a;
|
|
29126
|
+
}
|
|
29127
|
+
if (b !== null) {
|
|
29128
|
+
if (otherOwner >= 0) return null;
|
|
29129
|
+
otherOwner = i;
|
|
29130
|
+
}
|
|
29131
|
+
}
|
|
29132
|
+
return owner >= 0 && owner === otherOwner ? result : null;
|
|
29133
|
+
}
|
|
29134
|
+
};
|
|
29059
29135
|
function monoBox(o) {
|
|
29060
29136
|
const n = o.xs.length;
|
|
29061
29137
|
if (n === 0) {
|
|
@@ -29077,16 +29153,11 @@ function monoBox(o) {
|
|
|
29077
29153
|
let xMax = Math.floor((cxMax + 32) / 64);
|
|
29078
29154
|
let yMin = Math.floor((cyMin + 31) / 64);
|
|
29079
29155
|
let yMax = Math.floor((cyMax + 32) / 64);
|
|
29080
|
-
const
|
|
29081
|
-
|
|
29082
|
-
|
|
29083
|
-
|
|
29084
|
-
}
|
|
29085
|
-
if (yMin === yMax) {
|
|
29086
|
-
if (rem(cyMin, 31) + rem(cyMax, 32) < 0) yMin -= 1;
|
|
29087
|
-
else yMax += 1;
|
|
29088
|
-
}
|
|
29089
|
-
return { xMin, xMax, yMin, yMax };
|
|
29156
|
+
const collapsedX = xMin === xMax;
|
|
29157
|
+
const collapsedY = yMin === yMax;
|
|
29158
|
+
if (collapsedX) xMax += 1;
|
|
29159
|
+
if (collapsedY) yMax += 1;
|
|
29160
|
+
return { xMin, xMax, yMin, yMax, collapsedX, collapsedY };
|
|
29090
29161
|
}
|
|
29091
29162
|
function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossings26Dot6 = false) {
|
|
29092
29163
|
const box = fixedBox ?? monoBox(o);
|
|
@@ -29110,7 +29181,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29110
29181
|
const at = (col, row2) => (height - 1 - row2) * width + col;
|
|
29111
29182
|
const r = new Raster(dropout);
|
|
29112
29183
|
const P = r.precision;
|
|
29113
|
-
const monoContour = stubOvershoot && (dropout === 1 || dropout === 4 || dropout === 5)
|
|
29184
|
+
const monoContour = stubOvershoot && (dropout === 1 || dropout === 4 || dropout === 5) ? MonoStubContours.create(local) : null;
|
|
29114
29185
|
const smartPixel = (raster, x1, x2) => {
|
|
29115
29186
|
if (monoContour && smartCrossings26Dot6) {
|
|
29116
29187
|
const step = P / 64;
|
|
@@ -29153,7 +29224,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29153
29224
|
break;
|
|
29154
29225
|
case 1:
|
|
29155
29226
|
case 5:
|
|
29156
|
-
const stub = monoContour?.isStub(false, y, x1 / P, e2 / P, e1 / P, P);
|
|
29227
|
+
const stub = monoContour && box.collapsedX ? false : monoContour?.isStub(false, y, x1 / P, e2 / P, e1 / P, P, x2 / P);
|
|
29157
29228
|
if (stub === true) return;
|
|
29158
29229
|
if (stub == null && left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= r.half)) {
|
|
29159
29230
|
return;
|
|
@@ -29214,7 +29285,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29214
29285
|
break;
|
|
29215
29286
|
case 1:
|
|
29216
29287
|
case 5:
|
|
29217
|
-
const stub = monoContour?.isStub(true, col, x1 / P, e2 / P, e1 / P, P);
|
|
29288
|
+
const stub = monoContour && box.collapsedY ? false : monoContour?.isStub(true, col, x1 / P, e2 / P, e1 / P, P, x2 / P);
|
|
29218
29289
|
if (stub === true) return;
|
|
29219
29290
|
if (stub == null && left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= h.half)) {
|
|
29220
29291
|
return;
|
|
@@ -29578,6 +29649,7 @@ var RasterRealizedFont = class {
|
|
|
29578
29649
|
fsSelection: face.italic ? 1 : 0,
|
|
29579
29650
|
macStyle: 0,
|
|
29580
29651
|
winAscent: this.ascent,
|
|
29652
|
+
winDescent: this.descent,
|
|
29581
29653
|
unitsPerEm: this.ppem || 1
|
|
29582
29654
|
};
|
|
29583
29655
|
}
|
|
@@ -29765,6 +29837,11 @@ var RealizedFont = class {
|
|
|
29765
29837
|
}
|
|
29766
29838
|
return base + (this.syntheticBold ? 1 : 0);
|
|
29767
29839
|
}
|
|
29840
|
+
/** GDI+ rounds tracked hmtx advances to font units before device scaling. */
|
|
29841
|
+
designAdvance(index, tracking) {
|
|
29842
|
+
const { advance } = this.ttf.hMetrics(index < this.ttf.numGlyphs ? index : NOTDEF);
|
|
29843
|
+
return Math.round(advance * tracking) * this.ppemX / this.ttf.unitsPerEm + (this.syntheticBold ? 1 : 0);
|
|
29844
|
+
}
|
|
29768
29845
|
/**
|
|
29769
29846
|
* Advance of glyph `index` in a font realised with an escapement: GDI
|
|
29770
29847
|
* does not use the hinted/hdmx widths there but the linearly scaled
|
|
@@ -40452,6 +40529,35 @@ function surfaceSize5(ctx) {
|
|
|
40452
40529
|
return typeof w === "number" && typeof h === "number" && w > 0 && h > 0 ? { w, h } : null;
|
|
40453
40530
|
}
|
|
40454
40531
|
|
|
40532
|
+
// src/emf-plus-text-alignment.ts
|
|
40533
|
+
var SIMPLE_SCRIPT = /^(?:\p{Script=Latin}|\p{Script=Common}|\p{Co})$/u;
|
|
40534
|
+
var SHAPING_CHARACTER = /[\p{M}\p{Cf}\p{Emoji_Presentation}]/u;
|
|
40535
|
+
function layoutPlusAlignedString(font, codes, format, x, y, width, height) {
|
|
40536
|
+
const horizontal = format.alignment, vertical = format.lineAlignment;
|
|
40537
|
+
if (!horizontal && !vertical || horizontal < 0 || horizontal > 2 || vertical < 0 || vertical > 2 || font.gridFit || font.mode !== "gray" || !font.designAdvance || font.ttf.winDescent === void 0 || font.syntheticBold || font.syntheticItalic || format.flags & 3 || ![x, y, width, height].every(Number.isFinite) || width <= 0 || height <= 0 || codes.some((c) => !Number.isInteger(c) || c < 32 || c > 1114111 || c >= 127 && c <= 159 || c === 8232 || c === 8233)) return null;
|
|
40538
|
+
if (codes.some((c) => {
|
|
40539
|
+
const character = String.fromCodePoint(c);
|
|
40540
|
+
return !SIMPLE_SCRIPT.test(character) || SHAPING_CHARACTER.test(character) || font.glyphIndex(c) === 0;
|
|
40541
|
+
})) return null;
|
|
40542
|
+
const em = font.ppem;
|
|
40543
|
+
const tracking = format.tracking ?? 1.03;
|
|
40544
|
+
const leading = em * (format.leadingMargin ?? 1 / 6);
|
|
40545
|
+
const trailing = em * (format.trailingMargin ?? 1 / 6);
|
|
40546
|
+
if (![tracking, leading, trailing].every((v) => Number.isFinite(v) && v >= 0)) return null;
|
|
40547
|
+
if (!(format.flags & 4) && (font.ttf.fsSelection & 1 || font.ttf.macStyle & 2)) return null;
|
|
40548
|
+
const dx = codes.map((c) => font.designAdvance(font.glyphIndex(c), tracking));
|
|
40549
|
+
let measuredCount = codes.length;
|
|
40550
|
+
if (!(format.flags & 2048)) while (measuredCount > 0 && codes[measuredCount - 1] === 32) measuredCount--;
|
|
40551
|
+
const measuredWidth = dx.slice(0, measuredCount).reduce((a, b) => a + b, 0) + leading + trailing;
|
|
40552
|
+
const measuredHeight = em * (font.ttf.winAscent + font.ttf.winDescent) / font.ttf.unitsPerEm + (format.flags & 4 ? 0 : em / 8);
|
|
40553
|
+
if (measuredWidth > width || measuredHeight > height) return null;
|
|
40554
|
+
return {
|
|
40555
|
+
x: Math.fround(x + horizontal / 2 * (width - measuredWidth) + leading),
|
|
40556
|
+
y: Math.fround(y + vertical / 2 * (height - measuredHeight)) + Math.round(em * font.ttf.winAscent / font.ttf.unitsPerEm),
|
|
40557
|
+
dx
|
|
40558
|
+
};
|
|
40559
|
+
}
|
|
40560
|
+
|
|
40455
40561
|
// src/emf-plus-text-image-handlers.ts
|
|
40456
40562
|
function imageAttributesWrap(rCtx, attributesId) {
|
|
40457
40563
|
const obj = attributesId <= 255 ? rCtx.objectTable.get(attributesId) : void 0;
|
|
@@ -40720,25 +40826,33 @@ function paintPlusEngineRun(rCtx, ef, run) {
|
|
|
40720
40826
|
);
|
|
40721
40827
|
return true;
|
|
40722
40828
|
}
|
|
40723
|
-
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, alignment, format, brushSampler2 = null) {
|
|
40724
|
-
if (alignment !== 0) {
|
|
40725
|
-
return false;
|
|
40726
|
-
}
|
|
40829
|
+
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, layoutW, layoutH, paint, alignment, format, brushSampler2 = null) {
|
|
40727
40830
|
const ef = realizePlusEngineFont(rCtx, font, paint, brushSampler2);
|
|
40728
40831
|
if (!ef) {
|
|
40729
40832
|
return false;
|
|
40730
40833
|
}
|
|
40731
40834
|
const { realized, emPx, m, unhinted } = ef;
|
|
40835
|
+
const codes = Array.from(text, (character) => character.codePointAt(0));
|
|
40836
|
+
if (format && (alignment !== 0 || format.lineAlignment !== 0) && unhinted && m[0] === m[3] && Math.fround(emPx) === realized.ppem) {
|
|
40837
|
+
const aligned = layoutPlusAlignedString(
|
|
40838
|
+
realized,
|
|
40839
|
+
codes,
|
|
40840
|
+
format,
|
|
40841
|
+
m[0] * layoutX + m[4],
|
|
40842
|
+
m[3] * layoutY + m[5],
|
|
40843
|
+
m[0] * layoutW,
|
|
40844
|
+
m[3] * layoutH
|
|
40845
|
+
);
|
|
40846
|
+
if (aligned) return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, ...aligned, dy: null });
|
|
40847
|
+
}
|
|
40848
|
+
if (alignment !== 0) return false;
|
|
40732
40849
|
const ttf = realized.ttf;
|
|
40733
40850
|
const exactAscent = emPx * ttf.winAscent / ttf.unitsPerEm;
|
|
40734
|
-
const
|
|
40851
|
+
const clearTypeCell = realized.mode === "cleartype" && !realized.syntheticBold && !realized.syntheticItalic && emPx === realized.ppem && m[0] === 1 && m[3] === 1 && Number.isInteger(layoutY + m[5]) && (format?.lineAlignment ?? 0) === 0;
|
|
40852
|
+
const ascent = unhinted ? Math.round(exactAscent) : clearTypeCell ? Math.max(Math.round(exactAscent), realized.ascent) : Math.ceil(exactAscent);
|
|
40735
40853
|
let x = m[0] * layoutX + m[4] + emPx * (format?.leadingMargin ?? PLUS_LEADING_EM);
|
|
40736
40854
|
if (!unhinted) x = Math.round(x);
|
|
40737
40855
|
const y = m[3] * layoutY + m[5] + ascent;
|
|
40738
|
-
const codes = [];
|
|
40739
|
-
for (const character of text) {
|
|
40740
|
-
codes.push(character.codePointAt(0));
|
|
40741
|
-
}
|
|
40742
40856
|
const tracking = format?.tracking ?? PLUS_DEFAULT_TRACKING;
|
|
40743
40857
|
const dx = unhinted ? codes.map((c) => realized.advance(realized.glyphIndex(c)) * tracking) : null;
|
|
40744
40858
|
return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, x, y, dx, dy: null });
|
|
@@ -40820,8 +40934,8 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
40820
40934
|
const strLen = view.getUint32(dataOff + 8, true);
|
|
40821
40935
|
const layoutX = view.getFloat32(dataOff + 12, true);
|
|
40822
40936
|
const layoutY = view.getFloat32(dataOff + 16, true);
|
|
40823
|
-
view.getFloat32(dataOff + 20, true);
|
|
40824
|
-
view.getFloat32(dataOff + 24, true);
|
|
40937
|
+
const layoutW = view.getFloat32(dataOff + 20, true);
|
|
40938
|
+
const layoutH = view.getFloat32(dataOff + 24, true);
|
|
40825
40939
|
const fontId = recFlags & 255;
|
|
40826
40940
|
const font = objectTable.get(fontId);
|
|
40827
40941
|
if (strLen > 0 && dataOff + 28 + strLen * 2 <= dataOff + recDataSize) {
|
|
@@ -40837,6 +40951,8 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
40837
40951
|
text,
|
|
40838
40952
|
layoutX,
|
|
40839
40953
|
layoutY,
|
|
40954
|
+
layoutW,
|
|
40955
|
+
layoutH,
|
|
40840
40956
|
paint,
|
|
40841
40957
|
alignment,
|
|
40842
40958
|
format,
|
package/dist/index.mjs
CHANGED
|
@@ -29018,7 +29018,7 @@ var MonoStubContour = class {
|
|
|
29018
29018
|
constructor(o) {
|
|
29019
29019
|
this.points = Array.from(o.xs, (x, i) => [x / 64 - 0.5, o.ys[i] / 64 - 0.5]);
|
|
29020
29020
|
}
|
|
29021
|
-
isStub(flipped, scan, crossing, lo, hi, precision) {
|
|
29021
|
+
isStub(flipped, scan, crossing, lo, hi, precision, _opposite) {
|
|
29022
29022
|
const points = this.points;
|
|
29023
29023
|
const n = points.length;
|
|
29024
29024
|
const point = (i) => flipped ? [points[i][1], points[i][0]] : points[i];
|
|
@@ -29054,6 +29054,82 @@ var MonoStubContour = class {
|
|
|
29054
29054
|
return !(a.side * b.side < 0 && a.continues && b.continues);
|
|
29055
29055
|
}
|
|
29056
29056
|
};
|
|
29057
|
+
function convexContour(o) {
|
|
29058
|
+
const edges = [];
|
|
29059
|
+
for (let i = 0; i < o.xs.length; i++) {
|
|
29060
|
+
const j = (i + 1) % o.xs.length;
|
|
29061
|
+
const dx = o.xs[j] - o.xs[i], dy = o.ys[j] - o.ys[i];
|
|
29062
|
+
if (dx || dy) edges.push([dx, dy]);
|
|
29063
|
+
}
|
|
29064
|
+
if (edges.length < 3) return false;
|
|
29065
|
+
const half = (p) => p[1] > 0 || p[1] === 0 && p[0] >= 0 ? 0 : 1;
|
|
29066
|
+
let direction = 0, revolutions = 0;
|
|
29067
|
+
for (let i = 0; i < edges.length; i++) {
|
|
29068
|
+
const a = edges[i], b = edges[(i + 1) % edges.length];
|
|
29069
|
+
const cross = a[0] * b[1] - a[1] * b[0];
|
|
29070
|
+
if (!cross) {
|
|
29071
|
+
if (a[0] * b[0] + a[1] * b[1] < 0) return false;
|
|
29072
|
+
continue;
|
|
29073
|
+
}
|
|
29074
|
+
const turn = Math.sign(cross);
|
|
29075
|
+
if (direction && direction !== turn) return false;
|
|
29076
|
+
direction = turn;
|
|
29077
|
+
if (half(a) !== half(b) && half(a) === (turn > 0 ? 1 : 0)) revolutions++;
|
|
29078
|
+
}
|
|
29079
|
+
return direction !== 0 && revolutions === 1;
|
|
29080
|
+
}
|
|
29081
|
+
var MonoStubContours = class _MonoStubContours {
|
|
29082
|
+
constructor(contours) {
|
|
29083
|
+
this.contours = contours;
|
|
29084
|
+
}
|
|
29085
|
+
static create(o) {
|
|
29086
|
+
if (o.endPts.length > 64) return null;
|
|
29087
|
+
if (Array.from(o.onCurve).some((p) => !p)) return null;
|
|
29088
|
+
if (o.endPts.length === 1) return new MonoStubContour(o);
|
|
29089
|
+
const contours = [];
|
|
29090
|
+
const boxes = [];
|
|
29091
|
+
let start = 0;
|
|
29092
|
+
for (const end of o.endPts) {
|
|
29093
|
+
const xs = [], ys = [], onCurve = [];
|
|
29094
|
+
for (let i = start; i <= end; i++) {
|
|
29095
|
+
xs.push(o.xs[i]);
|
|
29096
|
+
ys.push(o.ys[i]);
|
|
29097
|
+
onCurve.push(o.onCurve[i]);
|
|
29098
|
+
}
|
|
29099
|
+
const part = { xs, ys, onCurve, endPts: [end - start] };
|
|
29100
|
+
start = end + 1;
|
|
29101
|
+
if (!convexContour(part)) return null;
|
|
29102
|
+
const box = { xMin: Infinity, xMax: -Infinity, yMin: Infinity, yMax: -Infinity };
|
|
29103
|
+
for (let i = 0; i < part.xs.length; i++) {
|
|
29104
|
+
box.xMin = Math.min(box.xMin, part.xs[i]);
|
|
29105
|
+
box.xMax = Math.max(box.xMax, part.xs[i]);
|
|
29106
|
+
box.yMin = Math.min(box.yMin, part.ys[i]);
|
|
29107
|
+
box.yMax = Math.max(box.yMax, part.ys[i]);
|
|
29108
|
+
}
|
|
29109
|
+
if (boxes.some((b) => box.xMin <= b.xMax + 64 && b.xMin <= box.xMax + 64 && box.yMin <= b.yMax + 64 && b.yMin <= box.yMax + 64)) return null;
|
|
29110
|
+
boxes.push(box);
|
|
29111
|
+
contours.push(new MonoStubContour(part));
|
|
29112
|
+
}
|
|
29113
|
+
return new _MonoStubContours(contours);
|
|
29114
|
+
}
|
|
29115
|
+
isStub(flipped, scan, crossing, lo, hi, precision, opposite) {
|
|
29116
|
+
let owner = -1, otherOwner = -1, result = null;
|
|
29117
|
+
for (let i = 0; i < this.contours.length; i++) {
|
|
29118
|
+
const a = this.contours[i].isStub(flipped, scan, crossing, lo, hi, precision);
|
|
29119
|
+
const b = this.contours[i].isStub(flipped, scan, opposite, lo, hi, precision);
|
|
29120
|
+
if (a !== null) {
|
|
29121
|
+
if (owner >= 0) return null;
|
|
29122
|
+
owner = i;
|
|
29123
|
+
result = a;
|
|
29124
|
+
}
|
|
29125
|
+
if (b !== null) {
|
|
29126
|
+
if (otherOwner >= 0) return null;
|
|
29127
|
+
otherOwner = i;
|
|
29128
|
+
}
|
|
29129
|
+
}
|
|
29130
|
+
return owner >= 0 && owner === otherOwner ? result : null;
|
|
29131
|
+
}
|
|
29132
|
+
};
|
|
29057
29133
|
function monoBox(o) {
|
|
29058
29134
|
const n = o.xs.length;
|
|
29059
29135
|
if (n === 0) {
|
|
@@ -29075,16 +29151,11 @@ function monoBox(o) {
|
|
|
29075
29151
|
let xMax = Math.floor((cxMax + 32) / 64);
|
|
29076
29152
|
let yMin = Math.floor((cyMin + 31) / 64);
|
|
29077
29153
|
let yMax = Math.floor((cyMax + 32) / 64);
|
|
29078
|
-
const
|
|
29079
|
-
|
|
29080
|
-
|
|
29081
|
-
|
|
29082
|
-
}
|
|
29083
|
-
if (yMin === yMax) {
|
|
29084
|
-
if (rem(cyMin, 31) + rem(cyMax, 32) < 0) yMin -= 1;
|
|
29085
|
-
else yMax += 1;
|
|
29086
|
-
}
|
|
29087
|
-
return { xMin, xMax, yMin, yMax };
|
|
29154
|
+
const collapsedX = xMin === xMax;
|
|
29155
|
+
const collapsedY = yMin === yMax;
|
|
29156
|
+
if (collapsedX) xMax += 1;
|
|
29157
|
+
if (collapsedY) yMax += 1;
|
|
29158
|
+
return { xMin, xMax, yMin, yMax, collapsedX, collapsedY };
|
|
29088
29159
|
}
|
|
29089
29160
|
function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossings26Dot6 = false) {
|
|
29090
29161
|
const box = fixedBox ?? monoBox(o);
|
|
@@ -29108,7 +29179,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29108
29179
|
const at = (col, row2) => (height - 1 - row2) * width + col;
|
|
29109
29180
|
const r = new Raster(dropout);
|
|
29110
29181
|
const P = r.precision;
|
|
29111
|
-
const monoContour = stubOvershoot && (dropout === 1 || dropout === 4 || dropout === 5)
|
|
29182
|
+
const monoContour = stubOvershoot && (dropout === 1 || dropout === 4 || dropout === 5) ? MonoStubContours.create(local) : null;
|
|
29112
29183
|
const smartPixel = (raster, x1, x2) => {
|
|
29113
29184
|
if (monoContour && smartCrossings26Dot6) {
|
|
29114
29185
|
const step = P / 64;
|
|
@@ -29151,7 +29222,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29151
29222
|
break;
|
|
29152
29223
|
case 1:
|
|
29153
29224
|
case 5:
|
|
29154
|
-
const stub = monoContour?.isStub(false, y, x1 / P, e2 / P, e1 / P, P);
|
|
29225
|
+
const stub = monoContour && box.collapsedX ? false : monoContour?.isStub(false, y, x1 / P, e2 / P, e1 / P, P, x2 / P);
|
|
29155
29226
|
if (stub === true) return;
|
|
29156
29227
|
if (stub == null && left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= r.half)) {
|
|
29157
29228
|
return;
|
|
@@ -29212,7 +29283,7 @@ function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true, smartCrossing
|
|
|
29212
29283
|
break;
|
|
29213
29284
|
case 1:
|
|
29214
29285
|
case 5:
|
|
29215
|
-
const stub = monoContour?.isStub(true, col, x1 / P, e2 / P, e1 / P, P);
|
|
29286
|
+
const stub = monoContour && box.collapsedY ? false : monoContour?.isStub(true, col, x1 / P, e2 / P, e1 / P, P, x2 / P);
|
|
29216
29287
|
if (stub === true) return;
|
|
29217
29288
|
if (stub == null && left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= h.half)) {
|
|
29218
29289
|
return;
|
|
@@ -29576,6 +29647,7 @@ var RasterRealizedFont = class {
|
|
|
29576
29647
|
fsSelection: face.italic ? 1 : 0,
|
|
29577
29648
|
macStyle: 0,
|
|
29578
29649
|
winAscent: this.ascent,
|
|
29650
|
+
winDescent: this.descent,
|
|
29579
29651
|
unitsPerEm: this.ppem || 1
|
|
29580
29652
|
};
|
|
29581
29653
|
}
|
|
@@ -29763,6 +29835,11 @@ var RealizedFont = class {
|
|
|
29763
29835
|
}
|
|
29764
29836
|
return base + (this.syntheticBold ? 1 : 0);
|
|
29765
29837
|
}
|
|
29838
|
+
/** GDI+ rounds tracked hmtx advances to font units before device scaling. */
|
|
29839
|
+
designAdvance(index, tracking) {
|
|
29840
|
+
const { advance } = this.ttf.hMetrics(index < this.ttf.numGlyphs ? index : NOTDEF);
|
|
29841
|
+
return Math.round(advance * tracking) * this.ppemX / this.ttf.unitsPerEm + (this.syntheticBold ? 1 : 0);
|
|
29842
|
+
}
|
|
29766
29843
|
/**
|
|
29767
29844
|
* Advance of glyph `index` in a font realised with an escapement: GDI
|
|
29768
29845
|
* does not use the hinted/hdmx widths there but the linearly scaled
|
|
@@ -40450,6 +40527,35 @@ function surfaceSize5(ctx) {
|
|
|
40450
40527
|
return typeof w === "number" && typeof h === "number" && w > 0 && h > 0 ? { w, h } : null;
|
|
40451
40528
|
}
|
|
40452
40529
|
|
|
40530
|
+
// src/emf-plus-text-alignment.ts
|
|
40531
|
+
var SIMPLE_SCRIPT = /^(?:\p{Script=Latin}|\p{Script=Common}|\p{Co})$/u;
|
|
40532
|
+
var SHAPING_CHARACTER = /[\p{M}\p{Cf}\p{Emoji_Presentation}]/u;
|
|
40533
|
+
function layoutPlusAlignedString(font, codes, format, x, y, width, height) {
|
|
40534
|
+
const horizontal = format.alignment, vertical = format.lineAlignment;
|
|
40535
|
+
if (!horizontal && !vertical || horizontal < 0 || horizontal > 2 || vertical < 0 || vertical > 2 || font.gridFit || font.mode !== "gray" || !font.designAdvance || font.ttf.winDescent === void 0 || font.syntheticBold || font.syntheticItalic || format.flags & 3 || ![x, y, width, height].every(Number.isFinite) || width <= 0 || height <= 0 || codes.some((c) => !Number.isInteger(c) || c < 32 || c > 1114111 || c >= 127 && c <= 159 || c === 8232 || c === 8233)) return null;
|
|
40536
|
+
if (codes.some((c) => {
|
|
40537
|
+
const character = String.fromCodePoint(c);
|
|
40538
|
+
return !SIMPLE_SCRIPT.test(character) || SHAPING_CHARACTER.test(character) || font.glyphIndex(c) === 0;
|
|
40539
|
+
})) return null;
|
|
40540
|
+
const em = font.ppem;
|
|
40541
|
+
const tracking = format.tracking ?? 1.03;
|
|
40542
|
+
const leading = em * (format.leadingMargin ?? 1 / 6);
|
|
40543
|
+
const trailing = em * (format.trailingMargin ?? 1 / 6);
|
|
40544
|
+
if (![tracking, leading, trailing].every((v) => Number.isFinite(v) && v >= 0)) return null;
|
|
40545
|
+
if (!(format.flags & 4) && (font.ttf.fsSelection & 1 || font.ttf.macStyle & 2)) return null;
|
|
40546
|
+
const dx = codes.map((c) => font.designAdvance(font.glyphIndex(c), tracking));
|
|
40547
|
+
let measuredCount = codes.length;
|
|
40548
|
+
if (!(format.flags & 2048)) while (measuredCount > 0 && codes[measuredCount - 1] === 32) measuredCount--;
|
|
40549
|
+
const measuredWidth = dx.slice(0, measuredCount).reduce((a, b) => a + b, 0) + leading + trailing;
|
|
40550
|
+
const measuredHeight = em * (font.ttf.winAscent + font.ttf.winDescent) / font.ttf.unitsPerEm + (format.flags & 4 ? 0 : em / 8);
|
|
40551
|
+
if (measuredWidth > width || measuredHeight > height) return null;
|
|
40552
|
+
return {
|
|
40553
|
+
x: Math.fround(x + horizontal / 2 * (width - measuredWidth) + leading),
|
|
40554
|
+
y: Math.fround(y + vertical / 2 * (height - measuredHeight)) + Math.round(em * font.ttf.winAscent / font.ttf.unitsPerEm),
|
|
40555
|
+
dx
|
|
40556
|
+
};
|
|
40557
|
+
}
|
|
40558
|
+
|
|
40453
40559
|
// src/emf-plus-text-image-handlers.ts
|
|
40454
40560
|
function imageAttributesWrap(rCtx, attributesId) {
|
|
40455
40561
|
const obj = attributesId <= 255 ? rCtx.objectTable.get(attributesId) : void 0;
|
|
@@ -40718,25 +40824,33 @@ function paintPlusEngineRun(rCtx, ef, run) {
|
|
|
40718
40824
|
);
|
|
40719
40825
|
return true;
|
|
40720
40826
|
}
|
|
40721
|
-
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, alignment, format, brushSampler2 = null) {
|
|
40722
|
-
if (alignment !== 0) {
|
|
40723
|
-
return false;
|
|
40724
|
-
}
|
|
40827
|
+
function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, layoutW, layoutH, paint, alignment, format, brushSampler2 = null) {
|
|
40725
40828
|
const ef = realizePlusEngineFont(rCtx, font, paint, brushSampler2);
|
|
40726
40829
|
if (!ef) {
|
|
40727
40830
|
return false;
|
|
40728
40831
|
}
|
|
40729
40832
|
const { realized, emPx, m, unhinted } = ef;
|
|
40833
|
+
const codes = Array.from(text, (character) => character.codePointAt(0));
|
|
40834
|
+
if (format && (alignment !== 0 || format.lineAlignment !== 0) && unhinted && m[0] === m[3] && Math.fround(emPx) === realized.ppem) {
|
|
40835
|
+
const aligned = layoutPlusAlignedString(
|
|
40836
|
+
realized,
|
|
40837
|
+
codes,
|
|
40838
|
+
format,
|
|
40839
|
+
m[0] * layoutX + m[4],
|
|
40840
|
+
m[3] * layoutY + m[5],
|
|
40841
|
+
m[0] * layoutW,
|
|
40842
|
+
m[3] * layoutH
|
|
40843
|
+
);
|
|
40844
|
+
if (aligned) return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, ...aligned, dy: null });
|
|
40845
|
+
}
|
|
40846
|
+
if (alignment !== 0) return false;
|
|
40730
40847
|
const ttf = realized.ttf;
|
|
40731
40848
|
const exactAscent = emPx * ttf.winAscent / ttf.unitsPerEm;
|
|
40732
|
-
const
|
|
40849
|
+
const clearTypeCell = realized.mode === "cleartype" && !realized.syntheticBold && !realized.syntheticItalic && emPx === realized.ppem && m[0] === 1 && m[3] === 1 && Number.isInteger(layoutY + m[5]) && (format?.lineAlignment ?? 0) === 0;
|
|
40850
|
+
const ascent = unhinted ? Math.round(exactAscent) : clearTypeCell ? Math.max(Math.round(exactAscent), realized.ascent) : Math.ceil(exactAscent);
|
|
40733
40851
|
let x = m[0] * layoutX + m[4] + emPx * (format?.leadingMargin ?? PLUS_LEADING_EM);
|
|
40734
40852
|
if (!unhinted) x = Math.round(x);
|
|
40735
40853
|
const y = m[3] * layoutY + m[5] + ascent;
|
|
40736
|
-
const codes = [];
|
|
40737
|
-
for (const character of text) {
|
|
40738
|
-
codes.push(character.codePointAt(0));
|
|
40739
|
-
}
|
|
40740
40854
|
const tracking = format?.tracking ?? PLUS_DEFAULT_TRACKING;
|
|
40741
40855
|
const dx = unhinted ? codes.map((c) => realized.advance(realized.glyphIndex(c)) * tracking) : null;
|
|
40742
40856
|
return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, x, y, dx, dy: null });
|
|
@@ -40818,8 +40932,8 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
40818
40932
|
const strLen = view.getUint32(dataOff + 8, true);
|
|
40819
40933
|
const layoutX = view.getFloat32(dataOff + 12, true);
|
|
40820
40934
|
const layoutY = view.getFloat32(dataOff + 16, true);
|
|
40821
|
-
view.getFloat32(dataOff + 20, true);
|
|
40822
|
-
view.getFloat32(dataOff + 24, true);
|
|
40935
|
+
const layoutW = view.getFloat32(dataOff + 20, true);
|
|
40936
|
+
const layoutH = view.getFloat32(dataOff + 24, true);
|
|
40823
40937
|
const fontId = recFlags & 255;
|
|
40824
40938
|
const font = objectTable.get(fontId);
|
|
40825
40939
|
if (strLen > 0 && dataOff + 28 + strLen * 2 <= dataOff + recDataSize) {
|
|
@@ -40835,6 +40949,8 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
40835
40949
|
text,
|
|
40836
40950
|
layoutX,
|
|
40837
40951
|
layoutY,
|
|
40952
|
+
layoutW,
|
|
40953
|
+
layoutH,
|
|
40838
40954
|
paint,
|
|
40839
40955
|
alignment,
|
|
40840
40956
|
format,
|