mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-30 01:27:26 +08:00
fix(编辑能力): 修复合字编辑显示异常
This commit is contained in:
1 parent
04efce42d8
commit
f322daa616
3 files changed
+42
-22
No files matched your search
@@ -3279,6 +3279,7 @@ button.outline-link:hover {
|
|||||||
|
|
||||||
.edit-text span[data-glyph]::after {
|
.edit-text span[data-glyph]::after {
|
||||||
content: attr(data-glyph);
|
content: attr(data-glyph);
|
||||||
|
letter-spacing: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
@@ -1851,12 +1851,15 @@ export class CanvasEditor {
|
|||||||
right = Math.max(right, x);
|
right = Math.max(right, x);
|
||||||
bottom = Math.max(bottom, y + lineHeight - baseline);
|
bottom = Math.max(bottom, y + lineHeight - baseline);
|
||||||
}
|
}
|
||||||
for (const char of run.text) {
|
const chars = [...run.text];
|
||||||
|
while (index < chars.length) {
|
||||||
|
const count = source.glyphCounts?.[glyphIndex] || 1;
|
||||||
|
const char = chars.slice(index, index + count).join("");
|
||||||
x = run.positions[index][0] * unit;
|
x = run.positions[index][0] * unit;
|
||||||
y = run.positions[index][1] * unit;
|
y = run.positions[index][1] * unit;
|
||||||
const span = document.createElement("span"), node = document.createTextNode(char);
|
const span = document.createElement("span"), node = document.createTextNode(char);
|
||||||
span.append(node);
|
span.append(node);
|
||||||
const glyph = source.glyphs?.[glyphIndex++];
|
const glyph = source.glyphs?.[glyphIndex];
|
||||||
if (glyph) {
|
if (glyph) {
|
||||||
span.dataset.glyph = glyph;
|
span.dataset.glyph = glyph;
|
||||||
glyphPositions.push({ span, start: position, end: position + char.length });
|
glyphPositions.push({ span, start: position, end: position + char.length });
|
||||||
@@ -1869,7 +1872,11 @@ export class CanvasEditor {
|
|||||||
positions.push({ node, start: position, end: position + char.length });
|
positions.push({ node, start: position, end: position + char.length });
|
||||||
position += char.length;
|
position += char.length;
|
||||||
const advance = context.measureText(glyph || char).width;
|
const advance = context.measureText(glyph || char).width;
|
||||||
if (glyph) span.style.width = `${advance}px`;
|
if (glyph) {
|
||||||
|
const naturalAdvance = [...char].reduce((width, value) => width + context.measureText(value).width, 0);
|
||||||
|
span.style.width = `${advance}px`;
|
||||||
|
span.style.letterSpacing = `${(advance - naturalAdvance) / count}px`;
|
||||||
|
}
|
||||||
for (const dx of [0, advance * scale]) {
|
for (const dx of [0, advance * scale]) {
|
||||||
for (const dy of [-baseline * vscale, (lineHeight - baseline) * vscale]) {
|
for (const dy of [-baseline * vscale, (lineHeight - baseline) * vscale]) {
|
||||||
const px = x + dx * cos - dy * sin, py = y + dx * sin + dy * cos;
|
const px = x + dx * cos - dy * sin, py = y + dx * sin + dy * cos;
|
||||||
@@ -1880,7 +1887,8 @@ export class CanvasEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
naturalX += advance;
|
naturalX += advance;
|
||||||
index++;
|
index += count;
|
||||||
|
glyphIndex += count;
|
||||||
}
|
}
|
||||||
if (!line.hasChildNodes()) {
|
if (!line.hasChildNodes()) {
|
||||||
const node = document.createTextNode("");
|
const node = document.createTextNode("");
|
||||||
|
|||||||
+29
-18
@@ -4353,9 +4353,28 @@ func (e *businessEngine) previewText(args []platformValue) (any, error) {
|
|||||||
} else if err := editor.RewriteTextWithFont(&text, args[2].String(), fontID); err != nil {
|
} else if err := editor.RewriteTextWithFont(&text, args[2].String(), fontID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
glyphs := make(map[int]string)
|
||||||
|
glyphCounts := make(map[int]int)
|
||||||
|
if fontID == "" {
|
||||||
|
for _, transform := range text.CGTransform {
|
||||||
|
if transform.CodeCount != transform.GlyphCount && transform.GlyphCount != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for i, value := range strings.Fields(transform.Glyphs) {
|
||||||
|
glyph, err := strconv.ParseUint(value, 10, 16)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
glyphs[transform.CodePosition+i] = string(rune(0xF0000 + glyph))
|
||||||
|
}
|
||||||
|
if transform.GlyphCount == 1 && transform.CodeCount > 1 {
|
||||||
|
glyphCounts[transform.CodePosition] = transform.CodeCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
var runs []any
|
var runs []any
|
||||||
var x, y float64
|
var x, y float64
|
||||||
value, offset := []rune(text.Text()), 0
|
value, offset, glyphOffset := []rune(text.Text()), 0, 0
|
||||||
for _, code := range text.TextCode {
|
for _, code := range text.TextCode {
|
||||||
if code.X != "" {
|
if code.X != "" {
|
||||||
x, _ = strconv.ParseFloat(code.X, 64)
|
x, _ = strconv.ParseFloat(code.X, 64)
|
||||||
@@ -4371,10 +4390,17 @@ func (e *businessEngine) previewText(args []platformValue) (any, error) {
|
|||||||
code.X, code.Y = fmt.Sprint(x), fmt.Sprint(y)
|
code.X, code.Y = fmt.Sprint(x), fmt.Sprint(y)
|
||||||
positioner := ofdgo.NewTextPositioner(code)
|
positioner := ofdgo.NewTextPositioner(code)
|
||||||
positions := make([][2]float64, len([]rune(content)))
|
positions := make([][2]float64, len([]rune(content)))
|
||||||
|
var point ofdgo.Point
|
||||||
|
remaining := 0
|
||||||
for i := range positions {
|
for i := range positions {
|
||||||
point := positioner.Next()
|
if remaining == 0 {
|
||||||
|
point = positioner.Next()
|
||||||
|
remaining = max(1, glyphCounts[glyphOffset+i])
|
||||||
|
}
|
||||||
positions[i] = [2]float64{point.X, point.Y}
|
positions[i] = [2]float64{point.X, point.Y}
|
||||||
|
remaining--
|
||||||
}
|
}
|
||||||
|
glyphOffset += len(positions)
|
||||||
runs = append(runs, map[string]any{"text": content, "x": x, "y": y, "positions": positions, "line": line})
|
runs = append(runs, map[string]any{"text": content, "x": x, "y": y, "positions": positions, "line": line})
|
||||||
offset += len(positions)
|
offset += len(positions)
|
||||||
}
|
}
|
||||||
@@ -4382,22 +4408,7 @@ func (e *businessEngine) previewText(args []platformValue) (any, error) {
|
|||||||
if scale == 0 {
|
if scale == 0 {
|
||||||
scale = 1
|
scale = 1
|
||||||
}
|
}
|
||||||
glyphs := make(map[int]string)
|
return map[string]any{"runs": runs, "glyphs": glyphs, "glyphCounts": glyphCounts, "scale": scale, "vscale": text.VScale, "rotation": text.CharDirection, "weight": text.Weight, "italic": text.Italic}, nil
|
||||||
if fontID == "" {
|
|
||||||
for _, transform := range text.CGTransform {
|
|
||||||
if transform.CodeCount != transform.GlyphCount {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for i, value := range strings.Fields(transform.Glyphs) {
|
|
||||||
glyph, err := strconv.ParseUint(value, 10, 16)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
glyphs[transform.CodePosition+i] = string(rune(0xF0000 + glyph))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map[string]any{"runs": runs, "glyphs": glyphs, "scale": scale, "vscale": text.VScale, "rotation": text.CharDirection, "weight": text.Weight, "italic": text.Italic}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// readTextSelection 将画布路径转换为同一容器的库层文字选区
|
// readTextSelection 将画布路径转换为同一容器的库层文字选区
|
||||||
|
|||||||
Reference in new issue
Block a user