office-gobmx/vcl/source/font/PhysicalFontFamily.cxx
DaeHyun Sung d9a31b8e16 tdf#125620 add Korean Hangul Jamo codepoint ranges
In LibreOffice's Korean Hangul part, It check Korean code points only 3 part ranges.
(such as,
U+AC00 - U+D7AF - Hangul Syllables
U+3130 - U+318F - Hangul Compatibility Jamo
U+1100 - U+11FF - Hangul Jamo )

So, add Korean Hangul jamo code point ranges.
such as,
U+A960 - U+A97F: Hangul Jamo Extended-A
U+D7B0 - U+D7FF: Hangul Jamo Extended-B

Below is Korean Hangul Jamo and Syllables code point ranges on Unicode Consortium
Hangul Jamo (Range: U+1100 - U+11FF)
http://www.unicode.org/charts/PDF/U1100.pdf
Hangul Jamo Extended-A (Range: U+A960 - U+A97F)
http://www.unicode.org/charts/PDF/UA960.pdf
Hangul Jamo Extended-B (Range: U+D7B0 - U+D7FF)
http://www.unicode.org/charts/PDF/UD7B0.pdf
Hangul Compatibility Jamo (Range: U+3130 - U+318F)
http://www.unicode.org/charts/PDF/U3130.pdf
Hangul Syllables (Range: U+AC00 - U+D7AF)
http://www.unicode.org/charts/PDF/UAC00.pdf

Change-Id: I65da4d9c6c43e01eb61f2e420faf1ad6cd986d86
Reviewed-on: https://gerrit.libreoffice.org/73309
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
2019-06-08 22:18:24 +02:00

273 lines
9.5 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <rtl/ustring.hxx>
#include <unotools/fontdefs.hxx>
#include <outdev.h>
#include <PhysicalFontCollection.hxx>
void PhysicalFontFamily::CalcType( ImplFontAttrs& rType, FontWeight& rWeight, FontWidth& rWidth,
FontFamily eFamily, const utl::FontNameAttr* pFontAttr )
{
if ( eFamily != FAMILY_DONTKNOW )
{
if ( eFamily == FAMILY_SWISS )
rType |= ImplFontAttrs::SansSerif;
else if ( eFamily == FAMILY_ROMAN )
rType |= ImplFontAttrs::Serif;
else if ( eFamily == FAMILY_SCRIPT )
rType |= ImplFontAttrs::Script;
else if ( eFamily == FAMILY_MODERN )
rType |= ImplFontAttrs::Fixed;
else if ( eFamily == FAMILY_DECORATIVE )
rType |= ImplFontAttrs::Decorative;
}
if ( pFontAttr )
{
rType |= pFontAttr->Type;
if ( ((rWeight == WEIGHT_DONTKNOW) || (rWeight == WEIGHT_NORMAL)) &&
(pFontAttr->Weight != WEIGHT_DONTKNOW) )
rWeight = pFontAttr->Weight;
if ( ((rWidth == WIDTH_DONTKNOW) || (rWidth == WIDTH_NORMAL)) &&
(pFontAttr->Width != WIDTH_DONTKNOW) )
rWidth = pFontAttr->Width;
}
}
static ImplFontAttrs lcl_IsCJKFont( const OUString& rFontName )
{
// Test, if Fontname includes CJK characters --> In this case we
// mention that it is a CJK font
for(int i = 0; i < rFontName.getLength(); i++)
{
const sal_Unicode ch = rFontName[i];
// japanese
if ( ((ch >= 0x3040) && (ch <= 0x30FF)) ||
((ch >= 0x3190) && (ch <= 0x319F)) )
return ImplFontAttrs::CJK|ImplFontAttrs::CJK_JP;
// korean
if ( ((ch >= 0xAC00) && (ch <= 0xD7AF)) ||
((ch >= 0xA960) && (ch <= 0xA97F)) ||
((ch >= 0xD7B0) && (ch <= 0xD7FF)) ||
((ch >= 0x3130) && (ch <= 0x318F)) ||
((ch >= 0x1100) && (ch <= 0x11FF)) )
return ImplFontAttrs::CJK|ImplFontAttrs::CJK_KR;
// chinese
if ( (ch >= 0x3400) && (ch <= 0x9FFF) )
return ImplFontAttrs::CJK|ImplFontAttrs::CJK_TC|ImplFontAttrs::CJK_SC;
// cjk
if ( ((ch >= 0x3000) && (ch <= 0xD7AF)) ||
((ch >= 0xFF00) && (ch <= 0xFFEE)) )
return ImplFontAttrs::CJK;
}
return ImplFontAttrs::None;
}
PhysicalFontFamily::PhysicalFontFamily( const OUString& rSearchName )
: maSearchName( rSearchName ),
mnTypeFaces( FontTypeFaces::NONE ),
meFamily( FAMILY_DONTKNOW ),
mePitch( PITCH_DONTKNOW ),
mnMinQuality( -1 ),
mnMatchType( ImplFontAttrs::None ),
meMatchWeight( WEIGHT_DONTKNOW ),
meMatchWidth( WIDTH_DONTKNOW )
{}
PhysicalFontFamily::~PhysicalFontFamily()
{
}
void PhysicalFontFamily::AddFontFace( PhysicalFontFace* pNewFontFace )
{
if( maFontFaces.empty() )
{
maFamilyName = pNewFontFace->GetFamilyName();
maMapNames = pNewFontFace->GetMapNames();
meFamily = pNewFontFace->GetFamilyType();
mePitch = pNewFontFace->GetPitch();
mnMinQuality = pNewFontFace->GetQuality();
}
else
{
if( meFamily == FAMILY_DONTKNOW )
meFamily = pNewFontFace->GetFamilyType();
if( mePitch == PITCH_DONTKNOW )
mePitch = pNewFontFace->GetPitch();
if( mnMinQuality > pNewFontFace->GetQuality() )
mnMinQuality = pNewFontFace->GetQuality();
}
// set attributes for attribute based font matching
mnTypeFaces |= FontTypeFaces::Scalable;
if( pNewFontFace->IsSymbolFont() )
mnTypeFaces |= FontTypeFaces::Symbol;
else
mnTypeFaces |= FontTypeFaces::NoneSymbol;
if( pNewFontFace->GetWeight() != WEIGHT_DONTKNOW )
{
if( pNewFontFace->GetWeight() >= WEIGHT_SEMIBOLD )
mnTypeFaces |= FontTypeFaces::Bold;
else if( pNewFontFace->GetWeight() <= WEIGHT_SEMILIGHT )
mnTypeFaces |= FontTypeFaces::Light;
else
mnTypeFaces |= FontTypeFaces::Normal;
}
if( pNewFontFace->GetItalic() == ITALIC_NONE )
mnTypeFaces |= FontTypeFaces::NoneItalic;
else if( (pNewFontFace->GetItalic() == ITALIC_NORMAL)
|| (pNewFontFace->GetItalic() == ITALIC_OBLIQUE) )
mnTypeFaces |= FontTypeFaces::Italic;
// reassign name (sharing saves memory)
if( pNewFontFace->GetFamilyName() == GetFamilyName() )
pNewFontFace->SetFamilyName( GetFamilyName() );
// add the new physical font face, replacing existing font face if necessary
// TODO: get rid of linear search?
auto it(maFontFaces.begin());
for (; it != maFontFaces.end(); ++it)
{
PhysicalFontFace* pFoundFontFace = it->get();
sal_Int32 eComp = pNewFontFace->CompareWithSize( *pFoundFontFace );
if( eComp > 0 )
continue;
if( eComp < 0 )
break;
// ignore duplicate if its quality is worse
if( pNewFontFace->GetQuality() < pFoundFontFace->GetQuality() )
return;
// keep the device font if its quality is good enough
if( pNewFontFace->GetQuality() == pFoundFontFace->GetQuality() )
return;
// replace existing font face with a better one
*it = pNewFontFace; // insert at sort position
return;
}
maFontFaces.emplace(it, pNewFontFace); // insert at sort position
}
// get font attributes using the normalized font family name
void PhysicalFontFamily::InitMatchData( const utl::FontSubstConfiguration& rFontSubst,
const OUString& rSearchName )
{
OUString aShortName;
OUString aMatchFamilyName(maMatchFamilyName);
// get font attributes from the decorated font name
utl::FontSubstConfiguration::getMapName( rSearchName, aShortName, aMatchFamilyName,
meMatchWeight, meMatchWidth, mnMatchType );
maMatchFamilyName = aMatchFamilyName;
const utl::FontNameAttr* pFontAttr = rFontSubst.getSubstInfo( rSearchName );
// eventually use the stripped name
if( !pFontAttr )
if( aShortName != rSearchName )
pFontAttr = rFontSubst.getSubstInfo( aShortName );
CalcType( mnMatchType, meMatchWeight, meMatchWidth, meFamily, pFontAttr );
mnMatchType |= lcl_IsCJKFont( maFamilyName );
}
PhysicalFontFace* PhysicalFontFamily::FindBestFontFace( const FontSelectPattern& rFSD ) const
{
if( maFontFaces.empty() )
return nullptr;
if( maFontFaces.size() == 1)
return maFontFaces[0].get();
// FontName+StyleName should map to FamilyName+StyleName
const OUString& rSearchName = rFSD.maTargetName;
OUString aTargetStyleName;
const OUString* pTargetStyleName = nullptr;
if((rSearchName.getLength() > maSearchName.getLength())
&& rSearchName.startsWith( maSearchName ) )
{
aTargetStyleName = rSearchName.copy(maSearchName.getLength() + 1);
pTargetStyleName = &aTargetStyleName;
}
// TODO: linear search improve!
PhysicalFontFace* pBestFontFace = maFontFaces[0].get();
FontMatchStatus aFontMatchStatus = {0,0,0, pTargetStyleName};
for (auto const& font : maFontFaces)
{
PhysicalFontFace* pFoundFontFace = font.get();
if( pFoundFontFace->IsBetterMatch( rFSD, aFontMatchStatus ) )
pBestFontFace = pFoundFontFace;
}
return pBestFontFace;
}
// update device font list with unique font faces, with uniqueness
// meaning different font attributes, but not different fonts sizes
void PhysicalFontFamily::UpdateDevFontList( ImplDeviceFontList& rDevFontList ) const
{
PhysicalFontFace* pPrevFace = nullptr;
for (auto const& font : maFontFaces)
{
PhysicalFontFace* pFoundFontFace = font.get();
if( !pPrevFace || pFoundFontFace->CompareIgnoreSize( *pPrevFace ) )
rDevFontList.Add( pFoundFontFace );
pPrevFace = pFoundFontFace;
}
}
void PhysicalFontFamily::GetFontHeights( std::set<int>& rHeights ) const
{
// add all available font heights
for (auto const& font : maFontFaces)
{
PhysicalFontFace *pFoundFontFace = font.get();
rHeights.insert( pFoundFontFace->GetHeight() );
}
}
void PhysicalFontFamily::UpdateCloneFontList(PhysicalFontCollection& rFontCollection) const
{
OUString aFamilyName = GetEnglishSearchFontName( GetFamilyName() );
PhysicalFontFamily* pFamily(nullptr);
for (auto const& font : maFontFaces)
{
PhysicalFontFace *pFoundFontFace = font.get();
if (!pFamily)
{ // tdf#98989 lazy create as family without faces won't work
pFamily = rFontCollection.FindOrCreateFontFamily(aFamilyName);
}
assert(pFamily);
pFamily->AddFontFace( pFoundFontFace );
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */