python ttf font weight_解决 font-weight 无效的问题

本文探讨了不同浏览器下font-weight属性的表现差异,特别是在MacOS下的Chrome、Firefox和Safari中。通过更改font-family属性,解决了字体重量的一致性问题。

近期调页面时有几个 font-weight 需要修改,无论怎么调整字体粗细都没有变化,深入研究后总结下文

初探

本地写个例子,代码如下

This is a paragraph

This is a paragraph

This is a paragraph

p {

font-size: 50px;

}

p.thin {

font-weight: 100;

}

p.normal {

font-weight: normal;

}

p.thick {

font-weight: bold;

}

在 Mac OS 下 Chrome、Firefox、Safari 结果分别如下(从左到右)

我的浏览器均为最新版本,发现一个简单的 font-weight 属性,在三个浏览器有三个表现。

Chrome 下所有字重均一样

Firefox 下表现正常,是我们期待的结果

Safari 下 100 无效,被解析为 normal

解决表现不一致的问题

这种不同浏览器表现不同是我们不能接受的,对于后期排错造成困难,于是我首先想到是字体的惹得货,修改我的样式文件

p {

font-size: 50px;

font-family: Arial;

}

p.thin {

font-weight: 100;

}

p.normal {

font-weight: normal;

}

p.thick {

font-weight: bold;

}

效果如下

这里的表现倒是一样的,我们可以忽略图中字体大小(截屏的误差导致),只看字体粗细就好,font-weight: 100; 都失效了。

MDN 文档的解释

This means that for fonts that provide only normal and bold, 100-500 are normal, and 600-900 are bold.

文章开始没有介绍基本语法,相信前端们都知道,normal 等同于 400, bold 等同于 700。

这也很好的解释了这个例子的表象,但我瞬间推翻了这句话,因为在例子1中 Firefox 在没有设置字体的情况下可以正常显示。

问题根源

到这里相信你已经知道答案了,我们要针对不同浏览器和运行环境进行全面配置 font-family 属性,全局的字体建议放在 body 选择器下。

p {

font-size: 50px;

font-family: -apple-system, BlinkMacSystemFont,

"Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",

"Fira Sans", "Droid Sans", "Helvetica Neue",

sans-serif;

}

p.thin {

font-weight: 100;

}

p.normal {

font-weight: normal;

}

p.thick {

font-weight: bold;

}

看下三个浏览器的表现

在字体和字重上达到了完全一致,仔细的观察会发现,Chrome 与 Safari 渲染不同字重的字体总宽度变化明显,而 Firefox 下则不是十分明显

温馨提示:尽量不要用字体去撑容器的宽度,尽量避免 hover 改变字重。因为不同环境下渲染的差异会导致表现不一致。

上面给的一大串字体又代表兼容那些环境和设备哪?

首先我们分成三组来解释

font-family:

/* 1 */ -apple-system, BlinkMacSystemFont,

/* 2 */ "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",

/* 3 */ "Helvetica Neue", sans-serif;

1.第一个分组是映射到系统 UI 字体的 CSS 属性。这涵盖了很多环境,并且不会将这些字体误认为别的字体

-apple-system 在 Mac OS X 和 iOS 上的 Safari 中设置 San Francisco,并在旧版本的 Mac OS X 上设置成 Neue Helvetica 和 Lucida Grande。它根据字体大小正确选择 San Francisco Text 和 San Francisco Display。

BlinkMacSystemFont 只针对于 Mac OS X 上的 Chrome。

2.第二个分组用于已知的系统 UI 字体

Segoe UI 针对 Windows 和 Windows Phone。

Roboto 针对 Android 和更高版本的 Chrome 操作系统。故意列出在 Segoe UI 后,因为如果你是 Windows 上的 Android 开发人员,并安装 Roboto,将使用 Segoe UI。

Oxygen 针对 KDE,Ubuntu,你可以猜到,Cantarell 针对 GNOME。这一开始感到徒劳,因为一些 Linux 发行版有许多这样的字体。

Fira Sans 针对 Firefox OS 系统。

Droid Sans 针对旧版本系统的安卓

请注意,我们不需要添加 San Francisco。在 iOS 和 Mac OS X 上,San Francisco 并不是显而易见的,而是作为“隐藏”字体存在。我们也不使用 .SFNSText-Regular,在 Mac OS X 上的 San Francisco 的内部 PostScript 名称来指定 San Francisco。它只适用于 Chrome,并且不如 BlinkMacSystemFont 通用。

3.第三个分组是我们的后备字体

Helvetica Neue 针对旧 El Capitan 版本的 Mac OS X。它被列在接近结尾,因为它是一个流行的字体在其他非 El Capitan 计算机上。

sans-serif 默认的是 sans-serif 后备字体。

以下是目前已知的的问题:

在 Mac OS X 的 Firefox 中,San Francisco 的字母间距比 Safari 和 Chrome 更紧。

它不会使 Lucida Grande 在 Mac OS X 的 pre-Yosemite 版本上降级到 Neue Helvetica。并且它可能不匹配不太受欢迎的操作系统上的正确字体或更复杂的配置。

说到这里上面都是英文的字体,我们需要针对中文设置字体,可以针对不同操作系统给中文字体。

总结

对于字体的统一展示,目前为止还没有完善的解决办法,只能针对不同设备给出对应的解决方案,至于为什么不引入外部的三方字库来统一字体呢?因为会增加网页的请求时长,渲染也会耗时,尽量避免三方字库。下次再有类似字重渲染误差问题可以先从字体下手,整个例子没有跑过 Windows 系统,可能在 Windows 下还会有问题。至少切入点有了改变,并不是 Chrome 下 font-weight 无效。

<think>好的,我现在需要解决用户的问题:如何在Python中获取字体的描边(stroke)或处理字体描边的库。首先,我得理解用户的具体需求。用户可能是在处理图像生成、文字渲染,或者需要为文本添加边框效果,比如在设计海报或生成带有特效的文字图片时用到。 首先,我应该回忆一下常见的Python图像处理库。Pillow(PIL)是一个常用的库,用于图像处理,可能支持文本描边。用户提到的描边通常是指在文字周围添加边框,这可以通过Pillow的ImageDraw模块来实现,比如先绘制一个较粗的轮廓,再在内部填充文字颜色。 然后,用户提到了引用中的内容,特别是引用[1]和[2]提到了Python中的字体描边方法。引用[1]中的代码示例使用了canvas.drawText,看起来像是Android的代码,但用户希望用Python实现。所以可能需要寻找类似功能的Python库。引用[2]提到了Pyecharts和一个新的绘图库,可能指的是Plotly或者其他的高级可视化库,但不确定是否直接支持文字描边。 接下来,我需要验证Pillow是否支持直接设置字体描边。查阅Pillow的文档,发现ImageDraw的text方法并没有直接的stroke参数。但可以通过多次绘制文本,调整位置和颜色来模拟描边效果。例如,先绘制多个偏移位置的文本作为边框,再在中心绘制填充色。 另外,OpenCV(cv2)也是一个可能的候选库,它处理图像更底层,可能提供更多控制。用户可以通过在图像上叠加不同颜色的文本来实现描边效果,但需要手动计算偏移量。 还有,用户提到的引用[3]是Java的实现,可能类似的方法可以应用到Python中,即生成文字图像并处理边缘像素来添加描边。但这种方法需要自己实现算法,可能比较复杂。 另一个可能性是使用矢量图形库,如Cairo(通过pycairo绑定),它支持更高级的绘图操作,包括路径描边。Cairo的文本渲染功能可以直接设置描边和填充,这可能更符合用户的需求。不过,pycairo的文档和社区支持可能不如Pillow广泛,需要一定的学习成本。 此外,可能需要检查是否有专门的字体处理库,比如fontTools,但它主要用于处理字体文件的结构,而不是渲染时的描边效果。用户的问题更偏向于渲染时的处理,而不是修改字体文件本身。 总结一下,可能的解决方案有: 1. 使用Pillow库,手动绘制多次文本实现描边。 2. 使用OpenCV进行图像处理,手动生成描边效果。 3. 使用pycairo库,利用其内置的描边功能。 4. 寻找第三方库,如reportlab(生成PDF时支持文本描边),或者matplotlib的扩展。 接下来需要详细说明每种方法的实现步骤,并给出代码示例。例如,使用Pillow时,可以创建一个空白图像,使用较大的字体尺寸多次绘制不同方向的轮廓,然后填充中心。或者,在绘制文本时,先绘制一个粗边的轮廓,再绘制内部填充。 需要确保代码正确,并符合用户提到的LaTeX格式要求。此外,需要检查引用中的信息是否相关,虽然用户提供的引用可能不完全对应,但可能需要参考其中的方法思路,比如使用多层绘制或调整绘制参数。 最后,生成相关问题,帮助用户进一步探索,比如如何处理抗锯齿、调整描边粗细,或者使用其他库的高级功能。</think>在Python中实现字体描边效果主要通过图像处理库或图形渲染库实现,以下是几种常用方法及示例: ### 一、使用Pillow(PIL)实现描边 通过多次绘制文本轮廓模拟描边效果: ```python from PIL import Image, ImageDraw, ImageFont # 创建画布 image = Image.new("RGB", (400, 200), (255, 255, 255)) draw = ImageDraw.Draw(image) font = ImageFont.truetype("arial.ttf", 40) text = "Hello World" position = (50, 50) # 描边参数 stroke_width = 5 stroke_color = "black" fill_color = "red" # 绘制描边(8方向偏移) offsets = [(dx, dy) for dx in (-1,0,1) for dy in (-1,0,1) if not (dx == 0 and dy == 0)] for dx, dy in offsets: draw.text((position[0]+dx*stroke_width, position[1]+dy*stroke_width), text, font=font, fill=stroke_color) # 填充中心文字 draw.text(position, text, font=font, fill=fill_color) image.save("stroke_text.png") ``` ### 二、使用OpenCV实现描边 通过膨胀操作生成轮廓: ```python import cv2 import numpy as np # 创建空白图像 image = np.zeros((200, 400, 3), dtype=np.uint8) + 255 text = "OpenCV Stroke" position = (50, 100) font = cv2.FONT_HERSHEY_SIMPLEX # 绘制描边(通过多次绘制不同位置) cv2.putText(image, text, position, font, 1, (0,0,0), 8, cv2.LINE_AA) # 黑色描边 cv2.putText(image, text, position, font, 1, (0,0,255), 2, cv2.LINE_AA) # 红色填充 cv2.imwrite("cv_stroke.jpg", image) ``` ### 三、使用pycairo实现矢量描边 (需安装`pycairo`库) ```python import cairo # 创建SVG表面 surface = cairo.SVGSurface("cairo_stroke.svg", 400, 200) ctx = cairo.Context(surface) # 设置文字参数 ctx.select_font_face("Arial", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) ctx.set_font_size(40) # 绘制描边 ctx.set
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值