Compare commits

..
1 Commits
Author SHA1 Message Date
alexrg 80ab99cc8a Bake La Salle branding into welcome wallpaper 2026-09-18 15:41:24 -06:00
6 changed files with 178 additions and 31 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 88 KiB

+26
View File
@@ -0,0 +1,26 @@
# SGU Credential Provider 0.6.5
Esta versión actualiza los fondos de bienvenida de Windows y Linux sin agregar
dependencias ni trabajo de composición durante el inicio de sesión.
## Identidad visual
- El fondo base azul incorpora de forma permanente el logotipo blanco oficial
de Universidad La Salle México.
- El generador utiliza directamente ese JPEG: no abre, redimensiona ni compone
un segundo archivo de logotipo cada vez que inicia una sesión.
- Se conservan las dimensiones institucionales de `1600x1000` y el área central
disponible para el saludo personalizado.
## Texto de ubicación
- La sala aparece en una primera línea de mayor tamaño.
- La dependencia aparece debajo con una tipografía menor.
- La redacción neutral usa `Acceso a...`; cuando Active Directory contiene el
sexo enriquecido, usa `Estás ubicado...` o `Estás ubicada...`.
- La misma lógica está incluida en los enrolamientos de Windows y Linux.
- Si faltan el sexo o los metadatos de ubicación, permanecen los fallbacks
neutrales documentados y el inicio de sesión no se bloquea.
Los perfiles de usuario locales y el rollback de roaming introducido en 0.6.4
no cambian en esta versión.
+16 -7
View File
@@ -1,7 +1,10 @@
# Fondo de bienvenida personalizado # Fondo de bienvenida personalizado
El enrolamiento instala un fondo base azul, las familias `Indivisa Text Sans` y El enrolamiento instala un fondo base azul que ya contiene el logotipo blanco
`Indivisa Text Serif`, y un generador local. La GPO de equipos oficial de Universidad La Salle México, las familias `Indivisa Text Sans` y
`Indivisa Text Serif`, y un generador local. El logotipo está horneado en
`assets/branding/darkblue.jpg`: el generador no carga, redimensiona ni compone
otro logo durante el inicio de sesión. La GPO de equipos
`SGU - Windows client experience` ejecuta el generador al abrir cada sesión y `SGU - Windows client experience` ejecuta el generador al abrir cada sesión y
mantiene el fondo base en la pantalla de bloqueo. mantiene el fondo base en la pantalla de bloqueo.
@@ -28,12 +31,18 @@ restaura el comando genérico de inicio.
El saludo usa `Bienvenido/ubicado` para `Male` y `Bienvenida/ubicada` para El saludo usa `Bienvenido/ubicado` para `Male` y `Bienvenida/ubicada` para
`Female`. Cuando el enriquecimiento no produjo este dato, utiliza la redacción `Female`. Cuando el enriquecimiento no produjo este dato, utiliza la redacción
neutral `Te damos la bienvenida` y `Ubicación:`. El texto secundario sigue estas neutral `Te damos la bienvenida` y `Acceso`. La ubicación se divide en dos
reglas: líneas: la sala ocupa la primera y la dependencia aparece debajo con un tamaño
menor. Sigue estas reglas:
1. Con `location` y OU: `Acceso al Aula Flexible del Centro de Experiencia Digital.` 1. Sin sexo: `Acceso a la Sala de Aplicaciones`, seguido por
2. Con sólo uno de los datos: muestra únicamente el dato disponible. `del Laboratorio de Cómputo de Ingeniería.`
3. Sin ambos: el texto adaptado `Bienvenido/Bienvenida al Laboratorio...`; sin 2. Masculino: `Estás ubicado en el Aula Flexible`, seguido por
`del Centro de Experiencia Digital.`
3. Femenino: `Estás ubicada en la Sala de Redes`, seguido por
`del Laboratorio de Cómputo de Ingeniería.`
4. Con sólo uno de los datos: muestra únicamente el dato disponible.
5. Sin ambos: el texto adaptado `Bienvenido/Bienvenida al Laboratorio...`; sin
sexo disponible, la forma neutral `Acceso al Laboratorio de Cómputo de Ingeniería.` sexo disponible, la forma neutral `Acceso al Laboratorio de Cómputo de Ingeniería.`
La ausencia de AD, de un atributo o de una tipografía nunca bloquea la sesión. La ausencia de AD, de un atributo o de una tipografía nunca bloquea la sesión.
+37 -9
View File
@@ -189,7 +189,7 @@ function Get-WelcomeLocationText {
$located = switch ($Gender) { $located = switch ($Gender) {
'Male' { 'Est{0}s ubicado en' -f [char]0x00E1 } 'Male' { 'Est{0}s ubicado en' -f [char]0x00E1 }
'Female' { 'Est{0}s ubicada en' -f [char]0x00E1 } 'Female' { 'Est{0}s ubicada en' -f [char]0x00E1 }
default { 'Ubicaci{0}n:' -f [char]0x00F3 } default { $null }
} }
$engineeringLab = switch ($Gender) { $engineeringLab = switch ($Gender) {
'Male' { 'Bienvenido al Laboratorio de C{0}mputo de Ingenier{1}a.' -f [char]0x00F3,[char]0x00ED } 'Male' { 'Bienvenido al Laboratorio de C{0}mputo de Ingenier{1}a.' -f [char]0x00F3,[char]0x00ED }
@@ -202,7 +202,10 @@ function Get-WelcomeLocationText {
if ($Room -and $OuName) { if ($Room -and $OuName) {
$roomArticle = Get-SpanishArticle -Value $Room $roomArticle = Get-SpanishArticle -Value $Room
$ouArticle = Get-SpanishArticle -Value $OuName $ouArticle = Get-SpanishArticle -Value $OuName
$roomPhrase = if ($roomArticle -eq 'el') { $roomPhrase = if ($Gender) {
if ($roomArticle) { "$roomArticle $Room" } else { $Room }
}
elseif ($roomArticle -eq 'el') {
"al $Room" "al $Room"
} }
elseif ($roomArticle) { elseif ($roomArticle) {
@@ -212,17 +215,26 @@ function Get-WelcomeLocationText {
"a $Room" "a $Room"
} }
$ouPhrase = if ($ouArticle -eq 'el') { "del $OuName" } elseif ($ouArticle) { "de $ouArticle $OuName" } else { "de $OuName" } $ouPhrase = if ($ouArticle -eq 'el') { "del $OuName" } elseif ($ouArticle) { "de $ouArticle $OuName" } else { "de $OuName" }
return "Acceso $roomPhrase $ouPhrase." $primary = if ($Gender) { "$located $roomPhrase" } else { "Acceso $roomPhrase" }
return "$primary`n$ouPhrase."
} }
if ($Room) { if ($Room) {
$article = Get-SpanishArticle -Value $Room $article = Get-SpanishArticle -Value $Room
$phrase = if ($article) { "$article $Room" } else { $Room } if ($Gender) {
return "$located $phrase." $phrase = if ($article) { "$article $Room" } else { $Room }
return "$located $phrase."
}
$destination = if ($article -eq 'el') { "al $Room" } elseif ($article) { "a $article $Room" } else { "a $Room" }
return "Acceso $destination."
} }
if ($OuName) { if ($OuName) {
$article = Get-SpanishArticle -Value $OuName $article = Get-SpanishArticle -Value $OuName
$phrase = if ($article) { "$article $OuName" } else { $OuName } if ($Gender) {
return "$located $phrase." $phrase = if ($article) { "$article $OuName" } else { $OuName }
return "$located $phrase."
}
$destination = if ($article -eq 'el') { "al $OuName" } elseif ($article) { "a $article $OuName" } else { "a $OuName" }
return "Acceso $destination."
} }
return $engineeringLab return $engineeringLab
} }
@@ -350,6 +362,9 @@ if (-not $PSBoundParameters.ContainsKey('OrganizationalUnit')) {
} }
} }
$locationText = Get-WelcomeLocationText -Room $Location -OuName $OrganizationalUnit -Gender $Gender $locationText = Get-WelcomeLocationText -Room $Location -OuName $OrganizationalUnit -Gender $Gender
$locationLines = @($locationText -split '\r?\n', 2)
$locationPrimaryText = $locationLines[0]
$locationSecondaryText = if ($locationLines.Count -gt 1) { $locationLines[1] } else { $null }
if (-not $CanvasWidth -or -not $CanvasHeight) { if (-not $CanvasWidth -or -not $CanvasHeight) {
try { try {
@@ -436,6 +451,8 @@ try {
-PreferredStyle ([Drawing.FontStyle]::Bold -bor [Drawing.FontStyle]::Italic) -PreferredStyle ([Drawing.FontStyle]::Bold -bor [Drawing.FontStyle]::Italic)
$locationFont = New-WelcomeFont -Family $sansFamily -Size ([single](27 * $scale)) ` $locationFont = New-WelcomeFont -Family $sansFamily -Size ([single](27 * $scale)) `
-PreferredStyle ([Drawing.FontStyle]::Regular) -PreferredStyle ([Drawing.FontStyle]::Regular)
$locationSecondaryFont = New-WelcomeFont -Family $sansFamily -Size ([single](20 * $scale)) `
-PreferredStyle ([Drawing.FontStyle]::Regular)
$format = [Drawing.StringFormat]::new() $format = [Drawing.StringFormat]::new()
$format.Alignment = [Drawing.StringAlignment]::Center $format.Alignment = [Drawing.StringAlignment]::Center
$format.LineAlignment = [Drawing.StringAlignment]::Center $format.LineAlignment = [Drawing.StringAlignment]::Center
@@ -447,11 +464,20 @@ try {
Draw-CenteredText -Graphics $graphics -Text $DisplayName -Font $nameFont ` Draw-CenteredText -Graphics $graphics -Text $DisplayName -Font $nameFont `
-Brush $whiteBrush -Bounds ([Drawing.RectangleF]::new($panelX + 30*$scale, $panelY + 64*$scale, $panelWidth - 60*$scale, 105*$scale)) -Format $format -Brush $whiteBrush -Bounds ([Drawing.RectangleF]::new($panelX + 30*$scale, $panelY + 64*$scale, $panelWidth - 60*$scale, 105*$scale)) -Format $format
$graphics.DrawLine($linePen, $panelX + 150*$scale, $panelY + 180*$scale, $panelX + $panelWidth - 150*$scale, $panelY + 180*$scale) $graphics.DrawLine($linePen, $panelX + 150*$scale, $panelY + 180*$scale, $panelX + $panelWidth - 150*$scale, $panelY + 180*$scale)
Draw-CenteredText -Graphics $graphics -Text $locationText -Font $locationFont ` if ($locationSecondaryText) {
-Brush $accentBrush -Bounds ([Drawing.RectangleF]::new($panelX + 60*$scale, $panelY + 190*$scale, $panelWidth - 120*$scale, 94*$scale)) -Format $format Draw-CenteredText -Graphics $graphics -Text $locationPrimaryText -Font $locationFont `
-Brush $accentBrush -Bounds ([Drawing.RectangleF]::new($panelX + 60*$scale, $panelY + 190*$scale, $panelWidth - 120*$scale, 46*$scale)) -Format $format
Draw-CenteredText -Graphics $graphics -Text $locationSecondaryText -Font $locationSecondaryFont `
-Brush $accentBrush -Bounds ([Drawing.RectangleF]::new($panelX + 60*$scale, $panelY + 235*$scale, $panelWidth - 120*$scale, 38*$scale)) -Format $format
}
else {
Draw-CenteredText -Graphics $graphics -Text $locationPrimaryText -Font $locationFont `
-Brush $accentBrush -Bounds ([Drawing.RectangleF]::new($panelX + 60*$scale, $panelY + 195*$scale, $panelWidth - 120*$scale, 78*$scale)) -Format $format
}
} }
finally { finally {
$format.Dispose() $format.Dispose()
$locationSecondaryFont.Dispose()
$locationFont.Dispose() $locationFont.Dispose()
$nameFont.Dispose() $nameFont.Dispose()
$welcomeFont.Dispose() $welcomeFont.Dispose()
@@ -519,6 +545,8 @@ Write-WelcomeLog -Message ("OK computer={0}; gender={1}; location={2}; ou={3}; o
Gender = $Gender Gender = $Gender
WelcomeHeading = $welcomeHeading WelcomeHeading = $welcomeHeading
LocationText = $locationText LocationText = $locationText
LocationPrimaryText = $locationPrimaryText
LocationSecondaryText = $locationSecondaryText
OutputPath = $OutputPath OutputPath = $OutputPath
Applied = -not $SkipApply Applied = -not $SkipApply
} }
+55 -13
View File
@@ -129,8 +129,8 @@ fi
article_for() { article_for() {
local value=${1,,} local value=${1,,}
case "$value" in case "$value" in
sala*|aula*|facultad*|unidad*|biblioteca*|oficina*|coordinación*) printf la ;; sala*|facultad*|unidad*|biblioteca*|oficina*|coordinación*) printf la ;;
laboratorio*|centro*|edificio*|campus*|taller*|auditorio*) printf el ;; aula*|laboratorio*|centro*|edificio*|campus*|taller*|auditorio*) printf el ;;
*) printf '' ;; *) printf '' ;;
esac esac
} }
@@ -159,29 +159,60 @@ case "$gender" in
;; ;;
*) *)
welcome_text='Te damos la bienvenida,' welcome_text='Te damos la bienvenida,'
located_text='Ubicación:' located_text=''
engineering_lab_text='Acceso al Laboratorio de Cómputo de Ingeniería.' engineering_lab_text='Acceso al Laboratorio de Cómputo de Ingeniería.'
;; ;;
esac esac
location_primary=''
location_secondary=''
if [[ -n $location && -n $organizational_unit ]]; then if [[ -n $location && -n $organizational_unit ]]; then
room_phrase=$(with_article "$location") room_article=$(article_for "$location")
if [[ -n $gender ]]; then
room_phrase=$(with_article "$location")
location_primary="${located_text} ${room_phrase}"
elif [[ $room_article == el ]]; then
location_primary="Acceso al ${location}"
elif [[ -n $room_article ]]; then
location_primary="Acceso a ${room_article} ${location}"
else
location_primary="Acceso a ${location}"
fi
ou_article=$(article_for "$organizational_unit") ou_article=$(article_for "$organizational_unit")
if [[ $ou_article == el ]]; then if [[ $ou_article == el ]]; then
ou_phrase="del ${organizational_unit}" location_secondary="del ${organizational_unit}."
elif [[ -n $ou_article ]]; then elif [[ -n $ou_article ]]; then
ou_phrase="de ${ou_article} ${organizational_unit}" location_secondary="de ${ou_article} ${organizational_unit}."
else else
ou_phrase="de ${organizational_unit}" location_secondary="de ${organizational_unit}."
fi fi
location_text="${located_text} ${room_phrase} ${ou_phrase}."
elif [[ -n $location ]]; then elif [[ -n $location ]]; then
location_text="${located_text} $(with_article "$location")." room_article=$(article_for "$location")
if [[ -n $gender ]]; then
location_primary="${located_text} $(with_article "$location")."
elif [[ $room_article == el ]]; then
location_primary="Acceso al ${location}."
elif [[ -n $room_article ]]; then
location_primary="Acceso a ${room_article} ${location}."
else
location_primary="Acceso a ${location}."
fi
elif [[ -n $organizational_unit ]]; then elif [[ -n $organizational_unit ]]; then
location_text="${located_text} $(with_article "$organizational_unit")." ou_article=$(article_for "$organizational_unit")
if [[ -n $gender ]]; then
location_primary="${located_text} $(with_article "$organizational_unit")."
elif [[ $ou_article == el ]]; then
location_primary="Acceso al ${organizational_unit}."
elif [[ -n $ou_article ]]; then
location_primary="Acceso a ${ou_article} ${organizational_unit}."
else
location_primary="Acceso a ${organizational_unit}."
fi
else else
location_text=$engineering_lab_text location_primary=$engineering_lab_text
fi fi
location_text=$location_primary
[[ -n $location_secondary ]] && location_text+=$'\n'"$location_secondary"
width=1600 width=1600
height=1000 height=1000
@@ -202,6 +233,7 @@ scale=$(( height * 100 / 1000 ))
welcome_size=$(( 34 * scale / 100 )) welcome_size=$(( 34 * scale / 100 ))
name_size=$(( 70 * scale / 100 )) name_size=$(( 70 * scale / 100 ))
location_size=$(( 27 * scale / 100 )) location_size=$(( 27 * scale / 100 ))
location_secondary_size=$(( 20 * scale / 100 ))
panel_width=$(( width * 76 / 100 )) panel_width=$(( width * 76 / 100 ))
panel_height=$(( 310 * scale / 100 )) panel_height=$(( 310 * scale / 100 ))
panel_x1=$(( (width - panel_width) / 2 )) panel_x1=$(( (width - panel_width) / 2 ))
@@ -232,6 +264,17 @@ if [[ $serif_font == DejaVu-Serif ]] && command -v fc-list >/dev/null 2>&1; then
fi fi
fi fi
location_annotations=(
-font "$sans_font" -weight 400 -style Normal -pointsize "$location_size"
-fill '#D3E2FF' -stroke none -annotate "+0+$(( 76 * scale / 100 ))" "$location_primary"
)
if [[ -n $location_secondary ]]; then
location_annotations+=(
-font "$sans_font" -weight 400 -style Normal -pointsize "$location_secondary_size"
-fill '#D3E2FF' -stroke none -annotate "+0+$(( 116 * scale / 100 ))" "$location_secondary"
)
fi
if ! "${image_command[@]}" "$BASE_IMAGE" \ if ! "${image_command[@]}" "$BASE_IMAGE" \
-resize "${width}x${height}^" -gravity center -extent "${width}x${height}" \ -resize "${width}x${height}^" -gravity center -extent "${width}x${height}" \
-fill 'rgba(0,13,58,0.30)' -draw "rectangle ${panel_x1},${panel_y1} ${panel_x2},${panel_y2}" \ -fill 'rgba(0,13,58,0.30)' -draw "rectangle ${panel_x1},${panel_y1} ${panel_x2},${panel_y2}" \
@@ -241,8 +284,7 @@ if ! "${image_command[@]}" "$BASE_IMAGE" \
-annotate "+0-$(( 92 * scale / 100 ))" "$welcome_text" \ -annotate "+0-$(( 92 * scale / 100 ))" "$welcome_text" \
-font "$serif_font" -weight 700 -style Italic -pointsize "$name_size" \ -font "$serif_font" -weight 700 -style Italic -pointsize "$name_size" \
-fill white -annotate "+0-$(( 22 * scale / 100 ))" "$display_name" \ -fill white -annotate "+0-$(( 22 * scale / 100 ))" "$display_name" \
-font "$sans_font" -weight 400 -style Normal -pointsize "$location_size" \ "${location_annotations[@]}" \
-fill '#D3E2FF' -annotate "+0+$(( 88 * scale / 100 ))" "$location_text" \
-quality 94 "$output_path" 2>>"$log_path"; then -quality 94 "$output_path" 2>>"$log_path"; then
fail_softly 'ImageMagick could not render the welcome wallpaper.' fail_softly 'ImageMagick could not render the welcome wallpaper.'
fi fi
+44 -2
View File
@@ -89,7 +89,29 @@ Describe 'Welcome wallpaper with AD metadata' {
$result = Invoke-WelcomeFixture -DirectoryGender $null ` $result = Invoke-WelcomeFixture -DirectoryGender $null `
-DirectoryLocation 'Aula Flexible' ` -DirectoryLocation 'Aula Flexible' `
-DirectoryOu 'Centro de Experiencia Digital' -DirectoryOu 'Centro de Experiencia Digital'
$result.LocationText | Should Be 'Acceso al Aula Flexible del Centro de Experiencia Digital.' $result.LocationText | Should Be "Acceso al Aula Flexible`ndel Centro de Experiencia Digital."
$result.LocationPrimaryText | Should Be 'Acceso al Aula Flexible'
$result.LocationSecondaryText | Should Be 'del Centro de Experiencia Digital.'
}
It 'uses the requested neutral, masculine and feminine location wording' {
$neutral = Invoke-WelcomeFixture -DirectoryGender $null `
-DirectoryLocation 'Sala de Aplicaciones' `
-DirectoryOu 'Laboratorio de Cómputo de Ingeniería'
$neutral.LocationPrimaryText | Should Be 'Acceso a la Sala de Aplicaciones'
$neutral.LocationSecondaryText | Should Be 'del Laboratorio de Cómputo de Ingeniería.'
$male = Invoke-WelcomeFixture -DirectoryGender 'Male' `
-DirectoryLocation 'Aula Flexible' `
-DirectoryOu 'Centro de Experiencia Digital'
$male.LocationPrimaryText | Should Be 'Estás ubicado en el Aula Flexible'
$male.LocationSecondaryText | Should Be 'del Centro de Experiencia Digital.'
$female = Invoke-WelcomeFixture -DirectoryGender 'Female' `
-DirectoryLocation 'Sala de Redes' `
-DirectoryOu 'Laboratorio de Cómputo de Ingeniería'
$female.LocationPrimaryText | Should Be 'Estás ubicada en la Sala de Redes'
$female.LocationSecondaryText | Should Be 'del Laboratorio de Cómputo de Ingeniería.'
} }
It 'keeps machine location metadata when the GPO command has no location arguments' { It 'keeps machine location metadata when the GPO command has no location arguments' {
@@ -98,6 +120,26 @@ Describe 'Welcome wallpaper with AD metadata' {
-DirectoryOu 'Laboratorio' ` -DirectoryOu 'Laboratorio' `
-MachineLocation 'Aula Flexible' ` -MachineLocation 'Aula Flexible' `
-MachineOu 'Centro de Experiencia Digital' -MachineOu 'Centro de Experiencia Digital'
$result.LocationText | Should Be 'Acceso al Aula Flexible del Centro de Experiencia Digital.' $result.LocationText | Should Be "Acceso al Aula Flexible`ndel Centro de Experiencia Digital."
}
It 'ships the logo inside the base image instead of compositing it at runtime' {
$source | Should Not Match 'lasalle-logo-blanco|DrawImage.*logo|composite.*logo'
$bitmap = [Drawing.Bitmap]::FromFile((Join-Path $repositoryRoot 'assets\branding\darkblue.jpg'))
try {
$whitePixels = 0
for ($x = 60; $x -lt 390; $x += 2) {
for ($y = 45; $y -lt 175; $y += 2) {
$pixel = $bitmap.GetPixel($x, $y)
if ($pixel.R -gt 220 -and $pixel.G -gt 220 -and $pixel.B -gt 220) {
$whitePixels++
}
}
}
($whitePixels -gt 250) | Should Be $true
}
finally {
$bitmap.Dispose()
}
} }
} }