mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-08-30 12:12:40 +08:00
feat(字体渲染): 加强字体渲染能力
This commit is contained in:
+25
-1
@@ -225,15 +225,39 @@ func hasUsableCmap(data []byte) bool {
|
|||||||
}
|
}
|
||||||
numTables := binary.BigEndian.Uint16(data[2:4])
|
numTables := binary.BigEndian.Uint16(data[2:4])
|
||||||
pos := 4
|
pos := 4
|
||||||
|
usable := false
|
||||||
for i := 0; i < int(numTables); i++ {
|
for i := 0; i < int(numTables); i++ {
|
||||||
if len(data) < pos+8 {
|
if len(data) < pos+8 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
platformID := binary.BigEndian.Uint16(data[pos : pos+2])
|
platformID := binary.BigEndian.Uint16(data[pos : pos+2])
|
||||||
|
encodingID := binary.BigEndian.Uint16(data[pos+2 : pos+4])
|
||||||
|
offset := binary.BigEndian.Uint32(data[pos+4 : pos+8])
|
||||||
|
if uint32(len(data)) < offset+2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
format := binary.BigEndian.Uint16(data[offset : offset+2])
|
||||||
|
if !supportedCmapFormat(format, platformID, encodingID) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if platformID == 0 || platformID == 3 {
|
if platformID == 0 || platformID == 3 {
|
||||||
return true
|
usable = true
|
||||||
}
|
}
|
||||||
pos += 8
|
pos += 8
|
||||||
}
|
}
|
||||||
|
return usable
|
||||||
|
}
|
||||||
|
|
||||||
|
// supportedCmapFormat 判断 cmap 子表格式是否可用
|
||||||
|
// 入参: format cmap 子表格式, platformID 平台ID, encodingID 编码ID
|
||||||
|
// 返回: bool 是否可用
|
||||||
|
func supportedCmapFormat(format, platformID, encodingID uint16) bool {
|
||||||
|
switch format {
|
||||||
|
case 0, 4, 6, 12:
|
||||||
|
return true
|
||||||
|
case 14:
|
||||||
|
return platformID == 0 && encodingID == 5
|
||||||
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
+31
-13
@@ -299,13 +299,13 @@ func (r *Renderer) renderLayer(ctx *canvas.Context, layer Layer, pageH float64,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, textObj := range layer.TextObject {
|
for _, textObj := range layer.TextObject {
|
||||||
r.renderText(ctx, textObj, pageH, defaultFill, defaultStroke, parentCTM)
|
r.renderText(ctx, textObj, pageH, defaultFill, defaultStroke, parentCTM, false)
|
||||||
}
|
}
|
||||||
for _, pathObj := range layer.PathObject {
|
for _, pathObj := range layer.PathObject {
|
||||||
r.renderPath(ctx, pathObj, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, false)
|
r.renderPath(ctx, pathObj, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, false)
|
||||||
}
|
}
|
||||||
for _, imgObj := range layer.ImageObject {
|
for _, imgObj := range layer.ImageObject {
|
||||||
r.renderImage(ctx, imgObj, pageH, parentCTM)
|
r.renderImage(ctx, imgObj, pageH, parentCTM, false)
|
||||||
}
|
}
|
||||||
for _, cgu := range layer.CompositeGraphicUnit {
|
for _, cgu := range layer.CompositeGraphicUnit {
|
||||||
r.renderCompositeGraphicUnit(ctx, cgu, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, false)
|
r.renderCompositeGraphicUnit(ctx, cgu, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, false)
|
||||||
@@ -353,7 +353,7 @@ func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu Composite
|
|||||||
}
|
}
|
||||||
for _, imgObj := range cgu.ImageObject {
|
for _, imgObj := range cgu.ImageObject {
|
||||||
imgObj.Alpha = mergeAlpha(imgObj.Alpha, cgu.Alpha)
|
imgObj.Alpha = mergeAlpha(imgObj.Alpha, cgu.Alpha)
|
||||||
r.renderImage(ctx, imgObj, pageH, ¤tCTM)
|
r.renderImage(ctx, imgObj, pageH, ¤tCTM, boundaryInCTM)
|
||||||
}
|
}
|
||||||
for _, pathObj := range cgu.PathObject {
|
for _, pathObj := range cgu.PathObject {
|
||||||
pathObj.Alpha = mergeAlpha(pathObj.Alpha, cgu.Alpha)
|
pathObj.Alpha = mergeAlpha(pathObj.Alpha, cgu.Alpha)
|
||||||
@@ -361,7 +361,7 @@ func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu Composite
|
|||||||
}
|
}
|
||||||
for _, textObj := range cgu.TextObject {
|
for _, textObj := range cgu.TextObject {
|
||||||
textObj.Alpha = mergeAlpha(textObj.Alpha, cgu.Alpha)
|
textObj.Alpha = mergeAlpha(textObj.Alpha, cgu.Alpha)
|
||||||
r.renderText(ctx, textObj, pageH, defaultFill, defaultStroke, ¤tCTM)
|
r.renderText(ctx, textObj, pageH, defaultFill, defaultStroke, ¤tCTM, boundaryInCTM)
|
||||||
}
|
}
|
||||||
for _, subCgu := range cgu.CompositeGraphicUnit {
|
for _, subCgu := range cgu.CompositeGraphicUnit {
|
||||||
subCgu.Alpha = mergeAlpha(subCgu.Alpha, cgu.Alpha)
|
subCgu.Alpha = mergeAlpha(subCgu.Alpha, cgu.Alpha)
|
||||||
@@ -375,11 +375,11 @@ func (r *Renderer) renderCompositeGraphicUnit(ctx *canvas.Context, cgu Composite
|
|||||||
func (r *Renderer) renderObject(ctx *canvas.Context, obj GraphicObject, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix, boundaryInCTM bool) {
|
func (r *Renderer) renderObject(ctx *canvas.Context, obj GraphicObject, pageH float64, defaultFill, defaultStroke color.Color, defaultLW float64, parentCTM *Matrix, boundaryInCTM bool) {
|
||||||
switch obj.Type {
|
switch obj.Type {
|
||||||
case "TextObject":
|
case "TextObject":
|
||||||
r.renderText(ctx, obj.TextObject, pageH, defaultFill, defaultStroke, parentCTM)
|
r.renderText(ctx, obj.TextObject, pageH, defaultFill, defaultStroke, parentCTM, boundaryInCTM)
|
||||||
case "PathObject":
|
case "PathObject":
|
||||||
r.renderPath(ctx, obj.PathObject, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, boundaryInCTM)
|
r.renderPath(ctx, obj.PathObject, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, boundaryInCTM)
|
||||||
case "ImageObject":
|
case "ImageObject":
|
||||||
r.renderImage(ctx, obj.ImageObject, pageH, parentCTM)
|
r.renderImage(ctx, obj.ImageObject, pageH, parentCTM, boundaryInCTM)
|
||||||
case "CompositeGraphicUnit", "CompositeObject":
|
case "CompositeGraphicUnit", "CompositeObject":
|
||||||
r.renderCompositeGraphicUnit(ctx, obj.CompositeGraphicUnit, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, boundaryInCTM)
|
r.renderCompositeGraphicUnit(ctx, obj.CompositeGraphicUnit, pageH, defaultFill, defaultStroke, defaultLW, parentCTM, boundaryInCTM)
|
||||||
}
|
}
|
||||||
@@ -471,8 +471,8 @@ func (r *Renderer) initCommon() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// renderImage 渲染图片
|
// renderImage 渲染图片
|
||||||
// 入参: ctx 画布上下文, obj 图片对象, pageH 页面高度, parentCTM 父级CTM
|
// 入参: ctx 画布上下文, obj 图片对象, pageH 页面高度, parentCTM 父级CTM, boundaryInCTM 边界是否参与父级CTM
|
||||||
func (r *Renderer) renderImage(ctx *canvas.Context, obj ImageObject, pageH float64, parentCTM *Matrix) {
|
func (r *Renderer) renderImage(ctx *canvas.Context, obj ImageObject, pageH float64, parentCTM *Matrix, boundaryInCTM bool) {
|
||||||
if obj.Visible != nil && !*obj.Visible {
|
if obj.Visible != nil && !*obj.Visible {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -501,13 +501,23 @@ func (r *Renderer) renderImage(ctx *canvas.Context, obj ImageObject, pageH float
|
|||||||
if obj.CTM == "" {
|
if obj.CTM == "" {
|
||||||
ctm = Matrix{a: box.W, d: box.H}
|
ctm = Matrix{a: box.W, d: box.H}
|
||||||
}
|
}
|
||||||
|
var m canvas.Matrix
|
||||||
|
if boundaryInCTM && parentCTM != nil {
|
||||||
|
x0 := box.X + ctm.c + ctm.e
|
||||||
|
y0 := box.Y + ctm.d + ctm.f
|
||||||
|
m = canvas.Matrix{
|
||||||
|
{(parentCTM.a*ctm.a + parentCTM.c*ctm.b) / imgW, -(parentCTM.a*ctm.c + parentCTM.c*ctm.d) / imgH, parentCTM.a*x0 + parentCTM.c*y0 + parentCTM.e},
|
||||||
|
{-(parentCTM.b*ctm.a + parentCTM.d*ctm.b) / imgW, (parentCTM.b*ctm.c + parentCTM.d*ctm.d) / imgH, pageH - (parentCTM.b*x0 + parentCTM.d*y0 + parentCTM.f)},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if parentCTM != nil {
|
if parentCTM != nil {
|
||||||
ctm = parentCTM.Multiply(ctm)
|
ctm = parentCTM.Multiply(ctm)
|
||||||
}
|
}
|
||||||
m := canvas.Matrix{
|
m = canvas.Matrix{
|
||||||
{ctm.a / imgW, -ctm.c / imgH, box.X + ctm.c + ctm.e},
|
{ctm.a / imgW, -ctm.c / imgH, box.X + ctm.c + ctm.e},
|
||||||
{-ctm.b / imgW, ctm.d / imgH, pageH - box.Y - ctm.d - ctm.f},
|
{-ctm.b / imgW, ctm.d / imgH, pageH - box.Y - ctm.d - ctm.f},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if pad > 0 {
|
if pad > 0 {
|
||||||
p := float64(pad)
|
p := float64(pad)
|
||||||
m[0][2] -= m[0][0]*p + m[0][1]*p
|
m[0][2] -= m[0][0]*p + m[0][1]*p
|
||||||
@@ -868,8 +878,8 @@ func patternColor(fillColor *FillColor) color.Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// renderText 渲染文本
|
// renderText 渲染文本
|
||||||
// 入参: ctx 画布上下文, obj 文本对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, parentCTM 父级CTM
|
// 入参: ctx 画布上下文, obj 文本对象, pageH 页面高度, defaultFill 默认填充色, defaultStroke 默认描边色, parentCTM 父级CTM, boundaryInCTM 边界是否参与父级CTM
|
||||||
func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64, defaultFill, defaultStroke color.Color, parentCTM *Matrix) {
|
func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64, defaultFill, defaultStroke color.Color, parentCTM *Matrix, boundaryInCTM bool) {
|
||||||
if obj.Visible != nil && !*obj.Visible {
|
if obj.Visible != nil && !*obj.Visible {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -880,7 +890,8 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
bx, by = box.X, box.Y
|
bx, by = box.X, box.Y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctm := NewMatrix(obj.CTM)
|
localCTM := NewMatrix(obj.CTM)
|
||||||
|
ctm := localCTM
|
||||||
if parentCTM != nil {
|
if parentCTM != nil {
|
||||||
ctm = parentCTM.Multiply(ctm)
|
ctm = parentCTM.Multiply(ctm)
|
||||||
}
|
}
|
||||||
@@ -1002,8 +1013,15 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
cy += dy
|
cy += dy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var canvasX, canvasY float64
|
||||||
|
if boundaryInCTM && parentCTM != nil {
|
||||||
|
tx, ty := localCTM.Transform(cx, cy)
|
||||||
|
tx, ty = parentCTM.Transform(tx+bx, ty+by)
|
||||||
|
canvasX, canvasY = tx, pageH-ty
|
||||||
|
} else {
|
||||||
tx, ty := ctm.Transform(cx, cy)
|
tx, ty := ctm.Transform(cx, cy)
|
||||||
canvasX, canvasY := tx+bx, pageH-(ty+by)
|
canvasX, canvasY = tx+bx, pageH-(ty+by)
|
||||||
|
}
|
||||||
textWidth := face.TextWidth(str) * hScale
|
textWidth := face.TextWidth(str) * hScale
|
||||||
glyphFillPaint := fillPaint
|
glyphFillPaint := fillPaint
|
||||||
if fillColorNode != nil && fillColorNode.AxialShd != nil {
|
if fillColorNode != nil && fillColorNode.AxialShd != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user