最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

r - Measuring the on-screen displayed width of strings in a parallel set-up - Stack Overflow

programmeradmin6浏览0评论

In order to adjust the columns' widths of a spreadheet document to their content, I need to compute the 'real' width in 'characters' (defined by Microsoft as the ratio of the real width divided by the real width of the corresponding string of the same length composed only of '0's) of strings for a specific font, say, Calibri (that I import and load in case it is not already registered in the system). While this works fine in a sequential set-up (I'm running on Windows) with the functions strwdith and par, when moving to a parallel set-up, the graphical parameters of the related function par are being slightly changed (and cannot be reversed back to the values I want) and the calculated width is then no longer correct. This behaviour is really surprising and unexpected to me as I thought that starting socket clusters on Windows would be equivalent to just open new identical sessions of R, esp. with identical graphical parameters.

Is there is an alternative way to reach the same outcome in a parallel set-up as in the sequential set-up?

Here is a reprex:

library(parallel)
library(extrafont)

if(is.null(fonts()))
{
    ttf_import(paths = file.path("...", "Input", "Fonts"))
    loadfonts()
}

par(family = "Calibri", ps = 11, font = 1)
ReferenceWidth <- strwidth('0', units = 'in')
MainWidth <- strwidth('One simple tentative', units = 'in')
print(c(MainWidth / ReferenceWidth, ReferenceWidth))

clusterMassiveExport <- makePSOCKcluster(names = 6)
ReferenceWidth_Vector <- unlist(parLapply(cl = clusterMassiveExport, X = 1, fun = function(x){
                    par(family = "Calibri", ps = 11, font = 1)
                    ReferenceWidth <- strwidth('0', units = 'in')
                    MainWidth <- strwidth('One simple tentative', units = 'in')
                    c(MainWidth / ReferenceWidth, ReferenceWidth)
                }))
stopCluster(clusterMassiveExport)
print(ReferenceWidth_Vector)

Results:

> print(c(MainWidth / ReferenceWidth, ReferenceWidth))
[1] 18.71428571  0.07291667

> print(ReferenceWidth_Vector)
[1] 20.00000000  0.07638889

Here are some addresses to download the Calibri font:

Regular

Bold

Italic

Bold italic

In order to adjust the columns' widths of a spreadheet document to their content, I need to compute the 'real' width in 'characters' (defined by Microsoft as the ratio of the real width divided by the real width of the corresponding string of the same length composed only of '0's) of strings for a specific font, say, Calibri (that I import and load in case it is not already registered in the system). While this works fine in a sequential set-up (I'm running on Windows) with the functions strwdith and par, when moving to a parallel set-up, the graphical parameters of the related function par are being slightly changed (and cannot be reversed back to the values I want) and the calculated width is then no longer correct. This behaviour is really surprising and unexpected to me as I thought that starting socket clusters on Windows would be equivalent to just open new identical sessions of R, esp. with identical graphical parameters.

Is there is an alternative way to reach the same outcome in a parallel set-up as in the sequential set-up?

Here is a reprex:

library(parallel)
library(extrafont)

if(is.null(fonts()))
{
    ttf_import(paths = file.path("...", "Input", "Fonts"))
    loadfonts()
}

par(family = "Calibri", ps = 11, font = 1)
ReferenceWidth <- strwidth('0', units = 'in')
MainWidth <- strwidth('One simple tentative', units = 'in')
print(c(MainWidth / ReferenceWidth, ReferenceWidth))

clusterMassiveExport <- makePSOCKcluster(names = 6)
ReferenceWidth_Vector <- unlist(parLapply(cl = clusterMassiveExport, X = 1, fun = function(x){
                    par(family = "Calibri", ps = 11, font = 1)
                    ReferenceWidth <- strwidth('0', units = 'in')
                    MainWidth <- strwidth('One simple tentative', units = 'in')
                    c(MainWidth / ReferenceWidth, ReferenceWidth)
                }))
stopCluster(clusterMassiveExport)
print(ReferenceWidth_Vector)

Results:

> print(c(MainWidth / ReferenceWidth, ReferenceWidth))
[1] 18.71428571  0.07291667

> print(ReferenceWidth_Vector)
[1] 20.00000000  0.07638889

Here are some addresses to download the Calibri font:

Regular

Bold

Italic

Bold italic

Share Improve this question edited Mar 24 at 0:18 Olivier7121 asked Mar 23 at 11:29 Olivier7121Olivier7121 4251 gold badge3 silver badges14 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I found a solution with the package systemfonts.

library(parallel)
library(systemfonts)

if(any(match_fonts("Calibri") == "sans"))   add_fonts(Sys.glob(file.path("...", "Input", "Fonts", "*.ttf")))
ResolutionPPI <- sqrt(prod(dev.size(units = c("px"))) / prod(dev.size(units = c("in"))))
dev.off()

ReferenceWidth <- string_width(strings = c('0'), family = "Calibri", size = 11, res = ResolutionPPI)
MainWidth <- string_width(strings = c('One simple tentative'), family = "Calibri", size = 11, res = ResolutionPPI)
print(c(MainWidth / ReferenceWidth, ReferenceWidth))

clusterMassiveExport <- makePSOCKcluster(names = 6)
clusterEvalQ(clusterMassiveExport, {
    lapply(c("systemfonts"), library, character.only = TRUE)
})
clusterExport(clusterMassiveExport, c("ResolutionPPI"))
print("After clusterExport in the socket approach")

ReferenceWidth_Vector <- unlist(parLapply(cl = clusterMassiveExport, X = 1:10, fun = function(x){
    ReferenceWidth <- string_width(strings = c('0'), family = "Calibri", size = 11, res = ResolutionPPI)
    MainWidth <- string_width(strings = c('One simple tentative'), family = "Calibri", size = 11, res = ResolutionPPI)
    c(MainWidth / ReferenceWidth, ReferenceWidth)
}))
stopCluster(clusterMassiveExport)
print(ReferenceWidth_Vector)
发布评论

评论列表(0)

  1. 暂无评论