首页 \ 问答 \ 画布描边文字锋利的文物(Canvas stroke text sharp artifacts)

画布描边文字锋利的文物(Canvas stroke text sharp artifacts)

我正在尝试画布笔划文本,当我使用大笔划线宽时,我注意到某些字母上有一个奇怪的神器。

问题出现在同一个字母上有时会出现不同的字体(但它实际上取决于字体系列/样式)。

代码片段尽可能简单明了:

(function() {
    var canvas = document.querySelector('#canvas');
    var ctx = canvas.getContext('2d');
    
    ctx.font = 'bold 110px "Arial"';
    ctx.lineWidth = 26;
    ctx.strokeStyle = '#a4ff11';
    ctx.strokeText('Water', 100, 100);
    
    ctx.fillStyle = '#ff0000';
    ctx.fillText('Water', 100, 100);
})();
<canvas id="canvas" width="800px" height="800px"></canvas>

我还链接了一个在我的浏览器中渲染的图像

这是一个常见的东西,我是一个笨拙的家伙,我还没弄明白(如果你充分增加字体大小它会消失)还是更多呢?


I am experimenting with canvas stroke text and I have noticed a strange artifact on some letters when using a large stroke line width.

The issue is present with different fonts sometimes on the same letters (but it really depends on the font family / style).

The snippet is as straightforward as possible:

(function() {
    var canvas = document.querySelector('#canvas');
    var ctx = canvas.getContext('2d');
    
    ctx.font = 'bold 110px "Arial"';
    ctx.lineWidth = 26;
    ctx.strokeStyle = '#a4ff11';
    ctx.strokeText('Water', 100, 100);
    
    ctx.fillStyle = '#ff0000';
    ctx.fillText('Water', 100, 100);
})();
<canvas id="canvas" width="800px" height="800px"></canvas>

I am also linking an image of how it renders in my browser(s):

Is this something common and I am such a clumsy guy that I haven't figure it out (it does go away if you increase the font size sufficiently) or is there more to it?


原文:https://stackoverflow.com/questions/31224680
更新时间:2022-03-18 20:03

最满意答案

无论你有多少线程,“需要维护秩序”只能直接表明你将按顺序执行任务。 在这种情况下,你最好只用一个线程来处理请求。

如果需求稍微宽松一点,你可以获得一些东西 - 例如,如果一个目的地的所有任务都需要按顺序排列,但是对于具有不同目的地的任务没有排序要求。 如果是这种情况,那么您的主队列解决方案将任务发送到每个单独线程的输入队列听起来非常好。

编辑:

动态指定线程/互斥锁的数量非常简单。 例如,要从命令行获取数字,您可以对此顺序执行某些操作(暂时不进行错误和完整性检查):

std::vector<pthread_t> threads;

int num_threads = atoi(argv[1]);
threads.resize(num_threads);

for (int i=0; i<num_threads; i++)
    pthread_create(&threads[i], NULL, thread_routine, NULL);

The "need to maintain order" all-but-directly states that you're going to be executing the tasks serially no matter how many threads you have. That being the case, you're probably best off with just one thread servicing the requests.

You could gain something if the requirement is a bit looser than that -- for example, if all the tasks for one destination need to remain in order, but there's no ordering requirement for tasks with different destinations. If this is the case, then your solution of a master queue sending tasks to an input queue for each individual thread sounds like quite a good one.

Edit:

Specifying the number of threads/mutexes dynamically is pretty easy. For example, to take the number from the command line, you could do something on this order (leaving out error and sanity checking for the moment):

std::vector<pthread_t> threads;

int num_threads = atoi(argv[1]);
threads.resize(num_threads);

for (int i=0; i<num_threads; i++)
    pthread_create(&threads[i], NULL, thread_routine, NULL);

相关问答

更多
  • C++ Thread 类[2022-10-21]

    线程是用来执行与程序进程相关的一些操作。 很多情况下,windows API只能完成少部分功能, 所以需要自己定义满足自己程序的相关操作,也称重载。
  • 你不能。 指针携带两条信息:内存中指向的位置和指向对象的类型。 有了void *这个最后的信息就被省略了,并且没有办法重构它指向的类型。 所以,你需要携带这个指针的另一个值来指定它实际指向的内容(你可以使用例如enum )。 在C ++中与此任务相关的唯一设备是RTTI,但它仅适用于指向多态类的指针(RTTI通常利用对象的vtable存储有关指针动态类型的附加信息,但可以访问vtable并只有在知道对象属于特定的多态类层次结构时才能正确解释)。 我正在寻找一种统一的方式来传递pid或tid,但会以不同的方式 ...
  • 函数mysql_thread_id()需要一个指向由本机MySQL C API的mysql_connect(...)函数创建的连接对象的指针。 Connector / C ++已将该对象埋藏得非常深(我看)。 MySQL的文档建议的替代方法是执行查询SELECT CONNECTION_ID() ,返回的结果将是您要查找的ID。 The function mysql_thread_id() expects a pointer to a connection object created by the nati ...
  • c_str()本身应该是线程安全的。 但是,如果你有另一个访问(写入)你正在使用c_str()的字符串的线程,那么你正在玩坐在汽油池中的匹配。 通常c_str()是通过在现有字符串的末尾添加零值(空字符0x00,而不是0的字符,即0x30)来实现的(如果还没有那个),并传回where的地址字符串存储。 有兴趣的人可以在这里阅读libstdc ++代码: libstdc ++,basic_string.h有趣的行是1802和294 - 1802是c_str()函数,294是c_str()调用的函数。 The ...
  • 无论你有多少线程,“需要维护秩序”只能直接表明你将按顺序执行任务。 在这种情况下,你最好只用一个线程来处理请求。 如果需求稍微宽松一点,你可以获得一些东西 - 例如,如果一个目的地的所有任务都需要按顺序排列,但是对于具有不同目的地的任务没有排序要求。 如果是这种情况,那么您的主队列解决方案将任务发送到每个单独线程的输入队列听起来非常好。 编辑: 动态指定线程/互斥锁的数量非常简单。 例如,要从命令行获取数字,您可以对此顺序执行某些操作(暂时不进行错误和完整性检查): std::vector
  • 否dThread dispatcher_threadloop()的dThread变量未初始化,因此取消引用它是一个错误。 看起来你应该将dThread传递给线程函数而不是dispatchQueue ,因为线程函数可以从前者获得后者。 像这样的东西(请注意,不需要向void *和void *进行转换): dispatch_queue_thread_t *dThread; dThread = malloc(sizeof *dThread); dThread->task = NULL; dThread->que ...
  • 迟到的答案,但是...从发行说明本身: 已知限制 The Perforce client-server protocol is not designed to support multiple concurrent queries over the same connection. For this reason, multi-threaded applications using the C++ API or the derived APIs (P4API. ...
  • 这是条件变量的工作。 查看boost文档的条件变量部分 - 这个例子几乎就是你正在做的。 无论你做什么,都不要随便睡一会儿 This is a job for condition variables. Check out the Condition Variables section of the boost docs - the example there is almost exactly what you're doing. Whatever you do, don't do a busy-wait ...
  • 线程池中的任务不应该阻止。 虽然已经在.NET 4.0中完成了工作以帮助支持它,但Threadpool并不适用于长时间运行的任务,当然也不适用于阻塞的操作(经验法则,如果线程启动时间可以忽略不计任务然后你最好开始自己的线程)。 对于你想要做的事情你可能会更好地使用IObservable东西。 看看Rx(Reactive)Extensions,你可以用IObservable做一些非常酷的事情。 默认情况下,IObservable一次只处理一个请求,但您可以轻松地将每个对象发送给您并将其抛出到线程池(用于实际处 ...
  • 最大的代价是在BackBuffer::write一个线程。 不要这样做,只需运行一个持久的后台线程并向其发送消息。 当前设置损坏输出缓冲区存在风险(在第一个缓冲区完成之前填充第二个缓冲区允许您再次开始覆盖第一个缓冲区)。 您可以通过使用完整缓冲区队列和空缓冲区队列来处理任意数量的缓冲区,以便在线程之间循环它们。 使后台线程负责创建新缓冲区,如果你低于一些最小级别的免费缓冲区,以保持动态分配不在关键循环中。 正如Voo所说,只是直接读入你的大缓冲区(并避免中间memcpy等)仍然更简单。 它确实比缓冲列表方法 ...

相关文章

更多

最新问答

更多
  • 您如何使用git diff文件,并将其应用于同一存储库的副本的本地分支?(How do you take a git diff file, and apply it to a local branch that is a copy of the same repository?)
  • 将长浮点值剪切为2个小数点并复制到字符数组(Cut Long Float Value to 2 decimal points and copy to Character Array)
  • OctoberCMS侧边栏不呈现(OctoberCMS Sidebar not rendering)
  • 页面加载后对象是否有资格进行垃圾回收?(Are objects eligible for garbage collection after the page loads?)
  • codeigniter中的语言不能按预期工作(language in codeigniter doesn' t work as expected)
  • 在计算机拍照在哪里进入
  • 使用cin.get()从c ++中的输入流中丢弃不需要的字符(Using cin.get() to discard unwanted characters from the input stream in c++)
  • No for循环将在for循环中运行。(No for loop will run inside for loop. Testing for primes)
  • 单页应用程序:页面重新加载(Single Page Application: page reload)
  • 在循环中选择具有相似模式的列名称(Selecting Column Name With Similar Pattern in a Loop)
  • System.StackOverflow错误(System.StackOverflow error)
  • KnockoutJS未在嵌套模板上应用beforeRemove和afterAdd(KnockoutJS not applying beforeRemove and afterAdd on nested templates)
  • 散列包括方法和/或嵌套属性(Hash include methods and/or nested attributes)
  • android - 如何避免使用Samsung RFS文件系统延迟/冻结?(android - how to avoid lag/freezes with Samsung RFS filesystem?)
  • TensorFlow:基于索引列表创建新张量(TensorFlow: Create a new tensor based on list of indices)
  • 企业安全培训的各项内容
  • 错误:RPC失败;(error: RPC failed; curl transfer closed with outstanding read data remaining)
  • C#类名中允许哪些字符?(What characters are allowed in C# class name?)
  • NumPy:将int64值存储在np.array中并使用dtype float64并将其转换回整数是否安全?(NumPy: Is it safe to store an int64 value in an np.array with dtype float64 and later convert it back to integer?)
  • 注销后如何隐藏导航portlet?(How to hide navigation portlet after logout?)
  • 将多个行和可变行移动到列(moving multiple and variable rows to columns)
  • 提交表单时忽略基础href,而不使用Javascript(ignore base href when submitting form, without using Javascript)
  • 对setOnInfoWindowClickListener的意图(Intent on setOnInfoWindowClickListener)
  • Angular $资源不会改变方法(Angular $resource doesn't change method)
  • 在Angular 5中不是一个函数(is not a function in Angular 5)
  • 如何配置Composite C1以将.m和桌面作为同一站点提供服务(How to configure Composite C1 to serve .m and desktop as the same site)
  • 不适用:悬停在悬停时:在元素之前[复制](Don't apply :hover when hovering on :before element [duplicate])
  • 常见的python rpc和cli接口(Common python rpc and cli interface)
  • Mysql DB单个字段匹配多个其他字段(Mysql DB single field matching to multiple other fields)
  • 产品页面上的Magento Up出售对齐问题(Magento Up sell alignment issue on the products page)