From c95ad6d50d9549451e01c351d8338d83a937d98a Mon Sep 17 00:00:00 2001 From: David Steele Date: Wed, 27 Oct 2021 13:17:54 +0100 Subject: [PATCH] Refactored font-client-plugin-impl Refactored cached item structs into separate classes with own methods. FontFaceCacheItem <|--- FontCacheItemInterface BitmapFontCacheItem <|-+ This simplifies a lot of the hidden type lookup within the plugin code. There is some scope for integrating EmbeddedItem into this interface as well. Change-Id: I7370355ff307f9aef7b19e2bbb6ed2225e7e92b6 Signed-off-by: David Steele --- automated-tests/resources/fonts/bitmap/u0030.png | Bin 0 -> 473 bytes automated-tests/resources/fonts/bitmap/u0031.png | Bin 0 -> 371 bytes automated-tests/resources/fonts/bitmap/u0032.png | Bin 0 -> 441 bytes automated-tests/resources/fonts/bitmap/u0033.png | Bin 0 -> 454 bytes automated-tests/resources/fonts/bitmap/u0034.png | Bin 0 -> 495 bytes automated-tests/resources/fonts/bitmap/u0035.png | Bin 0 -> 420 bytes automated-tests/resources/fonts/bitmap/u0036.png | Bin 0 -> 477 bytes automated-tests/resources/fonts/bitmap/u0037.png | Bin 0 -> 454 bytes automated-tests/resources/fonts/bitmap/u0038.png | Bin 0 -> 505 bytes automated-tests/resources/fonts/bitmap/u0039.png | Bin 0 -> 467 bytes automated-tests/resources/fonts/bitmap/u003a.png | Bin 0 -> 271 bytes .../src/dali-adaptor-internal/CMakeLists.txt | 1 + .../dali-adaptor-internal/utc-Dali-FontClient.cpp | 498 +++++++++++++- dali/devel-api/text-abstraction/font-client.h | 3 +- dali/internal/text/file.list | 3 + .../plugin/bitmap-font-cache-item.cpp | 140 ++++ .../plugin/bitmap-font-cache-item.h | 111 +++ .../text/text-abstraction/plugin/embedded-item.cpp | 61 ++ .../text/text-abstraction/plugin/embedded-item.h | 55 ++ .../plugin/font-cache-item-interface.h | 97 +++ .../plugin/font-client-plugin-impl.cpp | 758 ++------------------- .../plugin/font-client-plugin-impl.h | 87 +-- .../text-abstraction/plugin/font-client-utils.cpp | 2 + .../text-abstraction/plugin/font-client-utils.h | 4 + .../plugin/font-face-cache-item.cpp | 407 +++++++++++ .../text-abstraction/plugin/font-face-cache-item.h | 132 ++++ .../plugin/pixel-buffer-cache-item.h | 38 ++ 27 files changed, 1600 insertions(+), 797 deletions(-) create mode 100644 automated-tests/resources/fonts/bitmap/u0030.png create mode 100644 automated-tests/resources/fonts/bitmap/u0031.png create mode 100644 automated-tests/resources/fonts/bitmap/u0032.png create mode 100644 automated-tests/resources/fonts/bitmap/u0033.png create mode 100644 automated-tests/resources/fonts/bitmap/u0034.png create mode 100644 automated-tests/resources/fonts/bitmap/u0035.png create mode 100644 automated-tests/resources/fonts/bitmap/u0036.png create mode 100644 automated-tests/resources/fonts/bitmap/u0037.png create mode 100644 automated-tests/resources/fonts/bitmap/u0038.png create mode 100644 automated-tests/resources/fonts/bitmap/u0039.png create mode 100644 automated-tests/resources/fonts/bitmap/u003a.png create mode 100644 dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.cpp create mode 100644 dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h create mode 100644 dali/internal/text/text-abstraction/plugin/embedded-item.cpp create mode 100644 dali/internal/text/text-abstraction/plugin/embedded-item.h create mode 100644 dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h create mode 100644 dali/internal/text/text-abstraction/plugin/font-face-cache-item.cpp create mode 100644 dali/internal/text/text-abstraction/plugin/font-face-cache-item.h create mode 100644 dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h diff --git a/automated-tests/resources/fonts/bitmap/u0030.png b/automated-tests/resources/fonts/bitmap/u0030.png new file mode 100644 index 0000000000000000000000000000000000000000..1b0cc3c5e42e05280791f9f915e985ce0e28d24e GIT binary patch literal 473 zcmV;~0Ve*5P)qg=l}rhXaE2(J^%m^kmT%{ z>Hq)%Ur9tkRCwCVnB8&1AP|JtjNeTMaR*W=FeRh}myi-%f>J?}3gQyv4wMdX2TBE- z7m{%lzy}7BozaYbhWohFfF@I8QM)YV4_ZUNj?hGXry*C&9_uA|HL8&PYI!yg5Xok;ePQ6h?= z0%Q7`9-JXV8U!({3Y0yy)Hw-EIdChS5tHFsV3tu3*yNO5GH+MQycPT%08~bgC1u}9 z5>OdVFH-UxxTNHL4t!h4>Dh2mqXO_>@7y$U`swSWM&_L~0hKy7OO<>H-!&-t57Vl@ zGTXm_OPoGmd9DR$v#x6;uEw++BgOW&x3 z55_Gz131Li?IY{RhSvDY?eI_#I+HxOxZcf$Z?C4^WMMK(JYW0>i0X3yV%-$ydK660 P00000NkvXXu0mjf0|>$y literal 0 HcmV?d00001 diff --git a/automated-tests/resources/fonts/bitmap/u0031.png b/automated-tests/resources/fonts/bitmap/u0031.png new file mode 100644 index 0000000000000000000000000000000000000000..2c70e9c5c7c15792ec7c31a102ed1e489fda4bbe GIT binary patch literal 371 zcmV-(0gV2MP)qg=l}rhXaE2(J^%m^kmT%{ z>Hq)$`AI}URCwCdm(dZzAP_`1nG~QENC%+X~-WtFVm`$IeES|XnaFD=bv4@Uf#BL<9hh(I&OW z6Tr1JatWOCy=}|QT`Ty@_b2;B?2coS3m;p-i!?nKu1b`x=H|`dtftqB-EocjR!z@= zn^H~BffsA~-@#+CKe$b=vH6-}mI{wum2E9}(Wa-u)z;xju@8ywt{DaO9snN404oHA RUn~Fs002ovPDHLkV1mqwk17BF literal 0 HcmV?d00001 diff --git a/automated-tests/resources/fonts/bitmap/u0032.png b/automated-tests/resources/fonts/bitmap/u0032.png new file mode 100644 index 0000000000000000000000000000000000000000..2ed2d75c104c003c9f4a3961bef0117161336054 GIT binary patch literal 441 zcmV;q0Y?6bP)qg=l}rhXaE2(J^%m^kmT%{ z>Hq)%KS@MERCwCNm)miJFc3u#8vgBcKnJ0Nq=PsWm=4l{OK=HJ1xX2V2XY5=5M06L zNA~z3gk-aDXEgk1I9loIE)*g{M3!;ofSrGWi1dx6=xHk=l#x}|=;;e^W+pg56N6XE z@OsY5+j3yS{=pZ&CCuq!@b@RGS^+-;bF5L?(k^A&wcshc=Ct7TobaJ*dH^s=Rlg3M zHxP~23TPg1eaba+G5FT!ua+D@5ooD9V6B{PFFqg=l}rhXaE2(J^%m^kmT%{ z>Hq)%Oi4sRRCwCNm)%XnFcd~lBHrr_2osPIIzmTagpLq4V1%*(Y+yD>C!n1GcY@1H zh$5@DZ-SkCl3yZ6$M@f^M1+72z>$2q02VlnUqmFdIw_-GM2v_~M^3t@jGloHfGXm4 z2ka=Pr;z2QFc_c-!CO|)L+Dh%*HVjsN5#HA7W1Vtz)xb&HRksJ$N@J+%~JxdNmg45 zu1VH@OZX+#WR`-h!tGV8)TZiYwAxkyejiVeu)G1jGkWGc7~(WB?=pfvr{L5`Z8D8e zCnAS?j2QfsafUk)X?;d0=DB0d(DjUFuqg=l}rhXaE2(J^%m^kmT%{ z>Hq)%bxA})RCwCNmcem^FbqXM4ENB%x`WU`NCnvvD1j142b4fMa0yNaqyy3csX)1~ z84p?PZ{r2caDb8ZjJ_;66A|pN8bC+*H2|i6UqvMLDMe%!zx7)&_P`AR9$hhF!7Txv zMWjj%uY|M47b`~Ri2!RRUMO4>;Az=pQg}nAyJlmC=*%3eE+mtz&LaUfp~YJe-Khic z?D6?ox>ygOa`=q^TDHSoNu95Y{~U4(a>p(efPu)&2LKJA1n}hX9qktvTob{*tTa}{ zMkzR>^KDwq0r1H;)oN1bcC~IG);NzEJ0?xUlpB3;O-`$O?bBz&dX24l3*e2=?P}?4 zpNufQEzK3F^VY4Tj_LV@Rka|xm|pH}_p07!YPHs6%LUQ^c)@Y@4M61qnx(YKZZemH z;pPUfaJ>Efd3h$hJ^^k3AQKU_v*3DS2)%B>Q>4&Uu%BDm%@d^X!sz=5c+D2qBjAcH luCw5qe_kXgw)a^0?*Ma#^=IUqg=l}rhXaE2(J^%m^kmT%{ z>Hq)%DoI2^RCwCNm(g*9Fbsyj_!yuYlnv@m0NJ1;WQ2Butk4azLAyce26O|m0ZgF2 zlshi9593(kzvGF6&-x`x_CZ7ls0J?R>T-y{Ti{C>esqx+E&A$X@LCys1;)ML13(Pk zD8oB|Dl_Wqy!z5`pYZW%{=q$Rned^6_c`!M6TX)7zEstP;7=H-%E-3|&RaSeFa`@$ zM3&D<^fZXb%aZ2|JKH1hv1B;x^%{eZ25=vPe_C4L0-fs__*P_&v8^_5jW**@@$i?= zCbdabDbr_TK9k{lRQsR>Pw5l=Uhto_!E%q9RLe`l{T9nh!t2CI*M+9qS!`5?rkXd{ zVpA;V7Vv)!YrZIo0sMHo0B3Y5d=EwLlr5itx8(ui*7jB@`fhD7{SE+jG$mw#6X;(6 O0000qg=l}rhXaE2(J^%m^kmT%{ z>Hq)%V@X6oRCwCNm)&uLFc5@4Gk!-U(1Gc|?jY_UaR*KZxC56!DhM6K=>T`&5^x2V z7m*=GLIO+5&hP*OT5h%Xqm_u@fCAot5-13R4%n|9FIB)1$O(%R03u?$YKenRM3jh- zS^jJXyb=dzEjugAo;Sct1me5)%_O-*iuwT5{f)_RzK*{35zKISJ$$f~{G>DCDP$J2 zxzL2zgKS~s?SGM9L%GjHzIA+a3q`(OAi0`pwpKg+GEV5fC3P?H(CPJm`5t92iH98c z9A;BW@*YPUd69rz*~m8}M3z``YpVH3{ytINl-|#+N9v8peIma&N^1vv`4*|Uvb$>f ztiF)V`0(3f;l<<|U%4jWYRC8C0Fnii+-IHElxjtw{mz$=mrqJscy_v*sjD@T20K$% zQ;CXN>zZU@VKi!|B(H3ZrH)MeVH~#y1~^9=ohsW&`0=b(=#(k~nd>rjr1}{EYmyOq Tj~4g^00000NkvXXu0mjfWM9aw literal 0 HcmV?d00001 diff --git a/automated-tests/resources/fonts/bitmap/u0037.png b/automated-tests/resources/fonts/bitmap/u0037.png new file mode 100644 index 0000000000000000000000000000000000000000..ae3790a96a487b65ded2db3e7f3d8826acd590e2 GIT binary patch literal 454 zcmV;%0XhDOP)qg=l}rhXaE2(J^%m^kmT%{ z>Hq)%Oi4sRRCwCFm)miJFc3u#O#ZD7LMjL)P=ZTv36$UxC_yDq0`7ox;B-JL*!ZK4_ynBTH$KY1qB{T#(1hSM$HYAZZw`VF zA$WBF_y+K{@Uh)8FLl7DVqXt{h*&CnBbBH(wkJ|2Sg_@04#{S;HIA#r65z zQiV(X$VT8jvhV9}4Ji%Mrc;0cF8@|G%6-m}+d}qgmiv?{w}tFp0saZfy;1h7Qto!` zo;}m5kKL8(xi+o7XP>9FO=X79nzTB{z^R_M7Cz^AUR(K`>ba@Ush->VoZz`OpD#J} z!Xlr2Zf{uf+yQrG-ENZQj(9#K)a@y|J7kVSGPl!BE!ng`Z-Lj!>9e;QI-kehQ2`zw wGq)w&E63j2@+YGZk!p3?c+G&p@`vqr05!m&)HR%VQvd(}07*qoM6N<$f=}DP>;M1& literal 0 HcmV?d00001 diff --git a/automated-tests/resources/fonts/bitmap/u0038.png b/automated-tests/resources/fonts/bitmap/u0038.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b0d133a9391288846403ae632721667d20ff9c GIT binary patch literal 505 zcmVqg=l}rhXaE2(J^%m^kmT%{ z>Hq)%e@R3^RCwCFm(g*;Fc3r^8vf%Bpaa}NNC$KfN}vSNK}w(mcMzw7m<~h-rh>~4 zo`56y&bGwP@PllvZ+*8bFGK_d1+WK7V9h)E_ z#K^b67kP1Uk%a^Kv5HkLPawZ81AkgO`V6#@wGwzyJ3r9jJ43e~l_|08@#!K@t>L7s zw}w6ZRC2GZTV7q`CfxXK*myGeW@go$PYiZC(7FjvtdSSMt8z^Z5Snw#j1Ng~8M8N_ z4vk4Id2#BvLga;rG?|DG_gq6pkx~IKBI`a!%$G^*-Szh-vol1fPZ{WLgss*IZ1uq*UBV8 literal 0 HcmV?d00001 diff --git a/automated-tests/resources/fonts/bitmap/u0039.png b/automated-tests/resources/fonts/bitmap/u0039.png new file mode 100644 index 0000000000000000000000000000000000000000..2a3f481afd91fcbb20bd0388e67c36bfa0e94ede GIT binary patch literal 467 zcmV;^0WAKBP)qg=l}rhXaE2(J^%m^kmT%{ z>Hq)%SxH1eRCwCNm(f*(Fc3xW?%99oK&)WtKsspvl%XhjQ>1^zDsop?^8u>g4e+1zu@CkDjyL)qWx*y_8HFSsulBFKHneOaK)Ci zZ&j{!dJOnc8+B;-pPN!Bc;*y zd$&Bc=BfEE1=q`o-U3d6}R3@ zxyX6gfX8LN7uyTAmmIQ+i&LlcP0E{)_dwL@;8S%^?};pGtrLP856aiQ@OzOnX~jz6 zsaxd@m_GHfE?ewrvzPC>%f%m}4}!Q$I0I}hvt}?Kc+(#Km_LVU*7j<7U73PvS8u1F zueOCeDaY6Iu`1S*QGxzZY@-fbGu&3r!Qkzopr0I#-Q?EnA( literal 0 HcmV?d00001 diff --git a/automated-tests/src/dali-adaptor-internal/CMakeLists.txt b/automated-tests/src/dali-adaptor-internal/CMakeLists.txt index 0a8e771..b6c2ec9 100644 --- a/automated-tests/src/dali-adaptor-internal/CMakeLists.txt +++ b/automated-tests/src/dali-adaptor-internal/CMakeLists.txt @@ -60,6 +60,7 @@ ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror ) ADD_COMPILE_OPTIONS( ${${CAPI_LIB}_CFLAGS_OTHER} ) ADD_DEFINITIONS(-DTEST_IMAGE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../../images\" ) +ADD_DEFINITIONS(-DTEST_RESOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../../resources\" ) ADD_DEFINITIONS(-DADDON_LIBS_PATH=\"${CMAKE_CURRENT_BINARY_DIR}\" ) diff --git a/automated-tests/src/dali-adaptor-internal/utc-Dali-FontClient.cpp b/automated-tests/src/dali-adaptor-internal/utc-Dali-FontClient.cpp index ce9cfab..208deb1 100644 --- a/automated-tests/src/dali-adaptor-internal/utc-Dali-FontClient.cpp +++ b/automated-tests/src/dali-adaptor-internal/utc-Dali-FontClient.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -400,68 +401,499 @@ std::ostream& operator<<(std::ostream& o, const FontDescription& description) return o; } -int UtcDaliFontClientFindFallbackFont(void) +int UtcDaliFontClientGetDefaultPlatformFontDescription(void) { TestApplication application; - tet_infoline(" UtcDaliFontClientFindFallbackFont "); + tet_infoline(" UtcDaliFontClientGetDefaultPlatformFontDescription"); FontClient fontClient; fontClient = FontClient::Get(); - FontList fontList; - fontClient.GetSystemFonts(fontList); - DALI_TEST_CHECK(fontList.size() > 0); - - const std::string emptyString; - FontDescription fontDescription; - fontDescription.width = FontWidth::NORMAL; - fontDescription.weight = FontWeight::NORMAL; - fontDescription.slant = FontSlant::NORMAL; - fontDescription.type = FontDescription::BITMAP_FONT; + FontDescription fontDescription; + fontClient.GetDefaultPlatformFontDescription(fontDescription); std::ostringstream oss; oss << fontDescription; - tet_printf("Looking for: %s", oss.str().c_str()); + tet_printf("%s", oss.str().c_str()); + + DALI_TEST_CHECK(fontDescription.path.empty() == false); FontId fontId = fontClient.FindFallbackFont('A', fontDescription, FontClient::DEFAULT_POINT_SIZE, true); - DALI_TEST_CHECK(fontId != 0); - fontClient.GetDescription(fontId, fontDescription); - oss.clear(); - oss << fontDescription; - tet_printf("Found: %d: %s", fontId, oss.str().c_str()); - - bool color = fontClient.IsColorGlyph(fontId, fontClient.GetGlyphIndex(fontId, 'A')); - DALI_TEST_CHECK(color || 1); + bool supported = fontClient.IsCharacterSupportedByFont(fontId, 'A'); + DALI_TEST_EQUALS(supported, true, TEST_LOCATION); END_TEST; } -int UtcDaliFontClientGetDefaultPlatformFontDescription(void) +namespace +{ +constexpr uint8_t U1 = 1u; +constexpr uint8_t U2 = 2u; +constexpr uint8_t U3 = 3u; +constexpr uint8_t U4 = 4u; +constexpr uint8_t U5 = 5u; +constexpr uint8_t U6 = 6u; +constexpr uint8_t U0 = 0u; +constexpr uint8_t UTF8_LENGTH[256] = { + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // lead byte = 0xxx xxxx (U+0000 - U+007F + some extended ascii characters) + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, + U1, // + U1, + U1, // + + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, // + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, // lead byte = 110x xxxx (U+0080 - U+07FF) + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, + U2, // + U2, + U2, // + + U3, + U3, + U3, + U3, + U3, + U3, + U3, + U3, + U3, + U3, // lead byte = 1110 xxxx (U+0800 - U+FFFF) + U3, + U3, + U3, + U3, + U3, + U3, // + + U4, + U4, + U4, + U4, + U4, + U4, + U4, + U4, // lead byte = 1111 0xxx (U+10000 - U+1FFFFF) + + U5, + U5, + U5, + U5, // lead byte = 1111 10xx (U+200000 - U+3FFFFFF) + + U6, + U6, // lead byte = 1111 110x (U+4000000 - U+7FFFFFFF) + + U0, + U0, // Non valid. +}; + +constexpr uint8_t CR = 0xd; +constexpr uint8_t LF = 0xa; + +uint8_t GetUtf8Length(uint8_t utf8LeadByte) +{ + return UTF8_LENGTH[utf8LeadByte]; +} + +uint32_t Utf8ToUtf32(const uint8_t* const utf8, uint32_t length, uint32_t* utf32) +{ + uint32_t numberOfCharacters = 0u; + + const uint8_t* begin = utf8; + const uint8_t* end = utf8 + length; + + for(; begin < end; ++numberOfCharacters) + { + const uint8_t leadByte = *begin; + + switch(UTF8_LENGTH[leadByte]) + { + case U1: + { + if(CR == leadByte) + { + // Replace CR+LF or CR by LF + *utf32++ = LF; + + // Look ahead if the next one is a LF. + ++begin; + if(begin < end) + { + if(LF == *begin) + { + ++begin; + } + } + } + else + { + *utf32++ = leadByte; + begin++; + } + break; + } + + case U2: + { + uint32_t& code = *utf32++; + code = leadByte & 0x1fu; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U3: + { + uint32_t& code = *utf32++; + code = leadByte & 0x0fu; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U4: + { + uint32_t& code = *utf32++; + code = leadByte & 0x07u; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U5: + { + uint32_t& code = *utf32++; + code = leadByte & 0x03u; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U6: + { + uint32_t& code = *utf32++; + code = leadByte & 0x01u; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U0: // Invalid case + { + begin++; + *utf32++ = 0x20; // Use white space + break; + } + } + } + + return numberOfCharacters; +} + +TextAbstraction::FontId SetupBitmapFont() +{ + struct GlyphDesc + { + GlyphDesc() + { + } + GlyphDesc(const std::string& url, const std::string& utf8) + { + this->url = url; + std::copy(utf8.begin(), utf8.end(), this->utf8); + } + std::string url; + uint8_t utf8[4]; + }; + std::vector glyphs; + + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0030.png", ":"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0031.png", "0"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0032.png", "1"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0033.png", "2"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0034.png", "3"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0035.png", "4"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0036.png", "5"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0037.png", "6"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0038.png", "7"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0039.png", "8"}); + glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u003a.png", "9"}); + + TextAbstraction::BitmapFont bitmapFont; + bitmapFont.glyphs.reserve(glyphs.size()); + bitmapFont.name = "Digits"; + bitmapFont.underlinePosition = 0.f; + bitmapFont.underlineThickness = 0.f; + bitmapFont.isColorFont = true; + + for(const auto& glyph : glyphs) + { + uint32_t c = 0u; + Utf8ToUtf32(glyph.utf8, GetUtf8Length(glyph.utf8[0u]), &c); + TextAbstraction::BitmapGlyph bitmapGlyph(glyph.url, c, 34.f, 0.f); + bitmapFont.glyphs.push_back(std::move(bitmapGlyph)); + } + + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + return fontClient.GetFontId(bitmapFont); +} + +} // namespace + +int UtcDaliFontClientTestBitmapFont(void) { TestApplication application; - tet_infoline(" UtcDaliFontClientGetDefaultPlatformFontDescription"); + tet_infoline(" UtcDaliFontClientTestBitmapFont"); FontClient fontClient; fontClient = FontClient::Get(); - FontDescription fontDescription; - fontClient.GetDefaultPlatformFontDescription(fontDescription); + auto bitmapFontId = SetupBitmapFont(); + FontDescription fontDescription; + fontClient.GetDescription(bitmapFontId, fontDescription); std::ostringstream oss; oss << fontDescription; - tet_printf("%s", oss.str().c_str()); + tet_printf("Found: %d: %s", bitmapFontId, oss.str().c_str()); - DALI_TEST_CHECK(fontDescription.path.empty() == false); + bool color = fontClient.IsColorGlyph(bitmapFontId, fontClient.GetGlyphIndex(bitmapFontId, '2')); + DALI_TEST_EQUALS(color, true, TEST_LOCATION); - FontId fontId = fontClient.FindFallbackFont('A', - fontDescription, - FontClient::DEFAULT_POINT_SIZE, - true); + DALI_TEST_EQUALS(fontClient.GetPointSize(bitmapFontId), FontClient::DEFAULT_POINT_SIZE, TEST_LOCATION); + + DALI_TEST_EQUALS(fontClient.IsCharacterSupportedByFont(bitmapFontId, '3'), true, TEST_LOCATION); + DALI_TEST_EQUALS(fontClient.IsCharacterSupportedByFont(bitmapFontId, 'a'), false, TEST_LOCATION); - bool supported = fontClient.IsCharacterSupportedByFont(fontId, 'A'); - DALI_TEST_EQUALS(supported, true, TEST_LOCATION); END_TEST; } diff --git a/dali/devel-api/text-abstraction/font-client.h b/dali/devel-api/text-abstraction/font-client.h index ce00dd4..b1d6317 100644 --- a/dali/devel-api/text-abstraction/font-client.h +++ b/dali/devel-api/text-abstraction/font-client.h @@ -307,10 +307,11 @@ public: /** * @brief Retrieves a unique font identifier for a given bitmap font. + * If the font is not present, it will cache the given font, and give it a new font id. * * @param[in] bitmapFont A bitmap font. * - * @return A valid font identifier, or zero if no bitmap font is created. + * @return A valid font identifier. */ FontId GetFontId(const BitmapFont& bitmapFont); diff --git a/dali/internal/text/file.list b/dali/internal/text/file.list index fd617e2..7f00ae6 100644 --- a/dali/internal/text/file.list +++ b/dali/internal/text/file.list @@ -8,6 +8,9 @@ SET( adaptor_text_common_src_files ${adaptor_text_dir}/text-abstraction/shaping-impl.cpp ${adaptor_text_dir}/text-abstraction/text-renderer-impl.cpp ${adaptor_text_dir}/text-abstraction/hyphenation-impl.cpp + ${adaptor_text_dir}/text-abstraction/plugin/bitmap-font-cache-item.cpp + ${adaptor_text_dir}/text-abstraction/plugin/embedded-item.cpp ${adaptor_text_dir}/text-abstraction/plugin/font-client-utils.cpp ${adaptor_text_dir}/text-abstraction/plugin/font-client-plugin-impl.cpp + ${adaptor_text_dir}/text-abstraction/plugin/font-face-cache-item.cpp ) diff --git a/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.cpp b/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.cpp new file mode 100644 index 0000000..e7b5d43 --- /dev/null +++ b/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.cpp @@ -0,0 +1,140 @@ + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#if defined(DEBUG_ENABLED) +extern Dali::Integration::Log::Filter* gFontClientLogFilter; +#endif + +namespace Dali::TextAbstraction::Internal +{ +BitmapFontCacheItem::BitmapFontCacheItem(const BitmapFont& bitmapFont, FontId fontId) +: font(bitmapFont), + id(fontId) +{ + // Resize the vector with the pixel buffers. + pixelBuffers.resize(bitmapFont.glyphs.size()); + + // Traverse all the glyphs and load the pixel buffer of those with ascender and descender equal to zero. + unsigned int index = 0u; + for(auto& glyph : font.glyphs) + { + Devel::PixelBuffer& pixelBuffer = pixelBuffers[index]; + + if(EqualsZero(glyph.ascender) && EqualsZero(glyph.descender)) + { + // Load the glyph. + pixelBuffer = LoadImageFromFile(glyph.url); + + if(pixelBuffer) + { + glyph.ascender = static_cast(pixelBuffer.GetHeight()); + } + } + + font.ascender = std::max(glyph.ascender, font.ascender); + font.descender = std::min(glyph.descender, font.descender); + + ++index; + } +} + +void BitmapFontCacheItem::GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const +{ + metrics.ascender = font.ascender; + metrics.descender = font.descender; + metrics.height = metrics.ascender - metrics.descender; + metrics.underlinePosition = font.underlinePosition; + metrics.underlineThickness = font.underlineThickness; +} + +bool BitmapFontCacheItem::GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const +{ + bool success(false); + + unsigned int index = 0u; + for(auto& item : font.glyphs) + { + if(item.utf32 == glyph.index) + { + Devel::PixelBuffer& pixelBuffer = const_cast(pixelBuffers[index]); + if(!pixelBuffer) + { + pixelBuffer = LoadImageFromFile(item.url); + } + + glyph.width = static_cast(pixelBuffer.GetWidth()); + glyph.height = static_cast(pixelBuffer.GetHeight()); + glyph.xBearing = 0.f; + glyph.yBearing = glyph.height + item.descender; + glyph.advance = glyph.width; + glyph.scaleFactor = 1.f; + success = true; + break; + } + ++index; + } + return success; +} + +void BitmapFontCacheItem::CreateBitmap( + GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const +{ + unsigned int index = 0u; + for(auto& item : font.glyphs) + { + if(item.utf32 == glyphIndex) + { + Devel::PixelBuffer& pixelBuffer = const_cast(pixelBuffers[index]); + if(!pixelBuffer) + { + pixelBuffer = LoadImageFromFile(item.url); + } + + data.width = pixelBuffer.GetWidth(); + data.height = pixelBuffer.GetHeight(); + + data.isColorBitmap = font.isColorFont; + + ConvertBitmap(data, data.width, data.height, pixelBuffer.GetBuffer()); + + // Sets the pixel format. + data.format = pixelBuffer.GetPixelFormat(); + break; + } + ++index; + } +} + +bool BitmapFontCacheItem::IsCharacterSupported(Character character) +{ + for(const auto& glyph : font.glyphs) + { + if(glyph.utf32 == character) + { + return true; + } + } + return false; +} + +} // namespace Dali::TextAbstraction::Internal diff --git a/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h b/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h new file mode 100644 index 0000000..d8f083c --- /dev/null +++ b/dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h @@ -0,0 +1,111 @@ +#ifndef DALI_INTERNAL_TEXT_ABSTRACTION_BITMAP_FONT_CACHE_ITEM_H +#define DALI_INTERNAL_TEXT_ABSTRACTION_BITMAP_FONT_CACHE_ITEM_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// INTERNAL INCLUDES +#include +#include +#include + +#include +#include +#include FT_FREETYPE_H + +namespace Dali::TextAbstraction::Internal +{ +/** + * @brief Stores a bitmap font and its pixel buffers per glyph. + */ +struct BitmapFontCacheItem : public FontCacheItemInterface +{ + /** + * Constructor + * + * @param[in] bitmapFont The font to cache + * @param[in] fontId The id of the font + */ + BitmapFontCacheItem(const BitmapFont& bitmapFont, FontId fontId); + + /** + * @copydoc FontCacheItemInterface::GetFontMetrics() + */ + void GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const override; + + /** + * @copydoc FontCacheItemInterface::GetGlyphMetrics() + */ + bool GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const override; + + /** + * @copydoc FontCacheItemInterface::CreateBitmap() + */ + void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const override; + + /** + * @copydoc FontCacheItemInterface::IsColorGlyph() + */ + bool IsColorGlyph(GlyphIndex glyphIndex) const override + { + return true; + } + + /** + * @copydoc FontCacheItemInterface::IsCharacterSupported() + */ + bool IsCharacterSupported(Character character) override; + + /** + * @copydoc FontCacheItemInterface::GetPointSize() + */ + PointSize26Dot6 GetPointSize() const override + { + return TextAbstraction::FontClient::DEFAULT_POINT_SIZE; + } + + /** + * @copydoc FontCacheItemInterface::GetGlyphIndex() + */ + GlyphIndex GetGlyphIndex(Character character) const override + { + return 0u; + } + + /** + * @copydoc FontCacheItemInterface::GetTypeface() + */ + FT_Face GetTypeface() const override + { + return nullptr; + } + + /** + * @copydoc FontCacheItemInterface::HasItalicStyle() + */ + bool HasItalicStyle() const override + { + return false; + } + + BitmapFont font; ///< The bitmap font. + std::vector pixelBuffers; ///< The pixel buffers of the glyphs. + FontId id; ///< Index to the vector with the cache of font's ids. +}; + +} // namespace Dali::TextAbstraction::Internal + +#endif //DALI_INTERNAL_TEXT_ABSTRACTION_BITMAP_FONT_CACHE_ITEM_H diff --git a/dali/internal/text/text-abstraction/plugin/embedded-item.cpp b/dali/internal/text/text-abstraction/plugin/embedded-item.cpp new file mode 100644 index 0000000..cdec41f --- /dev/null +++ b/dali/internal/text/text-abstraction/plugin/embedded-item.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +namespace Dali::TextAbstraction::Internal +{ +void EmbeddedItem::GetGlyphMetrics(GlyphInfo& glyph) +{ + glyph.width = static_cast(width); + glyph.height = static_cast(height); + glyph.xBearing = 0.f; + glyph.yBearing = glyph.height; + glyph.advance = glyph.width; + glyph.scaleFactor = 1.f; +} + +void EmbeddedItem::CreateBitmap(const std::vector& pixelBufferCache, + Dali::TextAbstraction::FontClient::GlyphBufferData& data) +{ + data.width = width; + data.height = height; + if(0u != pixelBufferId) + { + Devel::PixelBuffer pixelBuffer = pixelBufferCache[pixelBufferId - 1u].pixelBuffer; + if(pixelBuffer) + { + ConvertBitmap(data, pixelBuffer.GetWidth(), pixelBuffer.GetHeight(), pixelBuffer.GetBuffer()); + + // Sets the pixel format. + data.format = pixelBuffer.GetPixelFormat(); + } + } + else + { + // Creates the output buffer + const unsigned int bufferSize = data.width * data.height * 4u; + data.buffer = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[]. + + memset(data.buffer, 0u, bufferSize); + + // Just creates a void buffer. Doesn't matter what pixel format is set as is the application code the responsible of filling it. + } +} + +} // namespace Dali::TextAbstraction::Internal diff --git a/dali/internal/text/text-abstraction/plugin/embedded-item.h b/dali/internal/text/text-abstraction/plugin/embedded-item.h new file mode 100644 index 0000000..9785a6d --- /dev/null +++ b/dali/internal/text/text-abstraction/plugin/embedded-item.h @@ -0,0 +1,55 @@ +#ifndef DALI_INTERNAL_TEXTABSTRACTION_PLUGIN_EMBEDDED_ITEM_H +#define DALI_INTERNAL_TEXTABSTRACTION_PLUGIN_EMBEDDED_ITEM_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +namespace Dali::TextAbstraction::Internal +{ +/** + * @brief Caches embedded items. + */ +struct EmbeddedItem +{ + /** + * Get metrics for glyph from image + * @param[in] item The embedded image + * @param[in,out] glyph The glyph to get metrics for + */ + void GetGlyphMetrics(GlyphInfo& glyph); + + /** + * @brief Create a glyph bitmap from an embedded item if present in the cache + * + * @param[in] pixelBufferCache The pixel buffer cache + * @param[out] data The bitmap data. + */ + void CreateBitmap(const std::vector& pixelBufferCache, + Dali::TextAbstraction::FontClient::GlyphBufferData& data); + + PixelBufferId pixelBufferId; ///< Index to the vector of pixel buffers + unsigned int width; ///< The desired width. + unsigned int height; ///< The desired height. +}; + +} // namespace Dali::TextAbstraction::Internal + +#endif //DALI_INTERNAL_TEXTABSTRACTION_PLUGIN_EMBEDDED_ITEM_H diff --git a/dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h b/dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h new file mode 100644 index 0000000..805719b --- /dev/null +++ b/dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h @@ -0,0 +1,97 @@ +#ifndef DALI_TEST_ABSTRACTION_INTERNAL_FONT_CACHE_ITEM_INTERFACE_H +#define DALI_TEST_ABSTRACTION_INTERNAL_FONT_CACHE_ITEM_INTERFACE_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include FT_FREETYPE_H + +namespace Dali::TextAbstraction::Internal +{ +struct FontCacheItemInterface +{ + /** + * Get the font metrics + * + * @param[out] metrics The metrics struct to fill out + */ + virtual void GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const = 0; + + /** + * Get glyph metrics + * + * @param[in,out] glyph The glyph to fill + */ + virtual bool GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const = 0; + + /** + * Create a bitmap for the given glyph + * + * @param[in] glyphIndex The index of the glyph + * @param[out] data The bitmap data for the glyph + * @param[in] outlineWidth + * @param[in] isItalicRequired + * @param[in] isBoldRequired + */ + virtual void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const = 0; + + /** + * Return true if the glyph is colored + * + * @param[in] glyphIndex The index of the glyph + * @return true if the glyph is colored + */ + virtual bool IsColorGlyph(GlyphIndex glyphIndex) const = 0; + + /** + * Check if the character is supported by this font + * @param[in] character The character to test + */ + virtual bool IsCharacterSupported(Character character) = 0; + + /** + * Get the point size of this font + * @return the point size + */ + virtual PointSize26Dot6 GetPointSize() const = 0; + + /** + * Get the index into this font's glyph table of the character + * + * @param[in] character to look up + * @return the glyph index of this character + */ + virtual GlyphIndex GetGlyphIndex(Character character) const = 0; + + /** + * Get the freetype typeface for this font. + */ + virtual FT_Face GetTypeface() const = 0; + + /** + * @return true if this font has an italic style + */ + virtual bool HasItalicStyle() const = 0; +}; + +} // namespace Dali::TextAbstraction::Internal + +#endif // DALI_TEST_ABSTRACTION_INTERNAL_FONT_CACHE_ITEM_INTERFACE_H diff --git a/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp b/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp index a7e025c..e438a53 100644 --- a/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp +++ b/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp @@ -26,7 +26,10 @@ #include #include #include +#include +#include #include +#include #include #include @@ -88,11 +91,7 @@ const uint32_t ELLIPSIS_CHARACTER = 0x2026; using Dali::Vector; using namespace std; -namespace Dali -{ -namespace TextAbstraction -{ -namespace Internal +namespace Dali::TextAbstraction::Internal { /** * @brief Free the resources allocated by the FcCharSet objects. @@ -258,52 +257,6 @@ FontClient::Plugin::FontDescriptionSizeCacheItem::FontDescriptionSizeCacheItem(F { } -FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem(FT_Face ftFace, - const FontPath& path, - PointSize26Dot6 requestedPointSize, - FaceIndex face, - const FontMetrics& metrics) -: mFreeTypeFace(ftFace), - mPath(path), - mRequestedPointSize(requestedPointSize), - mFaceIndex(face), - mMetrics(metrics), - mCharacterSet(nullptr), - mFixedSizeIndex(0), - mFixedWidthPixels(0.f), - mFixedHeightPixels(0.f), - mVectorFontId(0u), - mFontId(0u), - mIsFixedSizeBitmap(false), - mHasColorTables(false) -{ -} - -FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem(FT_Face ftFace, - const FontPath& path, - PointSize26Dot6 requestedPointSize, - FaceIndex face, - const FontMetrics& metrics, - int fixedSizeIndex, - float fixedWidth, - float fixedHeight, - bool hasColorTables) -: mFreeTypeFace(ftFace), - mPath(path), - mRequestedPointSize(requestedPointSize), - mFaceIndex(face), - mMetrics(metrics), - mCharacterSet(nullptr), - mFixedSizeIndex(fixedSizeIndex), - mFixedWidthPixels(fixedWidth), - mFixedHeightPixels(fixedHeight), - mVectorFontId(0u), - mFontId(0u), - mIsFixedSizeBitmap(true), - mHasColorTables(hasColorTables) -{ -} - FontClient::Plugin::Plugin(unsigned int horizontalDpi, unsigned int verticalDpi) : mFreeTypeLibrary(nullptr), @@ -634,37 +587,16 @@ PointSize26Dot6 FontClient::Plugin::GetPointSize(FontId id) { DALI_LOG_TRACE_METHOD(gFontClientLogFilter); DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", id); - const FontId index = id - 1u; - if((id > 0u) && - (index < mFontIdCache.Count())) + PointSize26Dot6 pointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE; + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(id); + if(fontCacheItem != nullptr) { - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; - - switch(fontIdCacheItem.type) - { - case FontDescription::FACE_FONT: - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " point size : %d\n", (*(mFontFaceCache.begin() + fontIdCacheItem.id)).mRequestedPointSize); - return (*(mFontFaceCache.begin() + fontIdCacheItem.id)).mRequestedPointSize; - } - case FontDescription::BITMAP_FONT: - { - return TextAbstraction::FontClient::DEFAULT_POINT_SIZE; - } - default: - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid type of font\n"); - } - } - } - else - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid font ID %d\n", id); + pointSize = fontCacheItem->GetPointSize(); } + DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " point size : %d\n", pointSize); - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " default point size : %d\n", TextAbstraction::FontClient::DEFAULT_POINT_SIZE); - return TextAbstraction::FontClient::DEFAULT_POINT_SIZE; + return pointSize; } bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character character) @@ -673,77 +605,40 @@ bool FontClient::Plugin::IsCharacterSupportedByFont(FontId fontId, Character cha DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " font id : %d\n", fontId); DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " character : %p\n", character); - if((fontId < 1u) || (fontId > mFontIdCache.Count())) + bool isSupported = false; + auto fontCacheItem = const_cast(GetCachedFontItem(fontId)); + if(fontCacheItem != nullptr) { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid font id. Number of items in the cache: %d\n", mFontIdCache.Count()); - return false; + isSupported = fontCacheItem->IsCharacterSupported(character); // May cache } - --fontId; - - bool isSupported = false; - - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[fontId]; + DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " is supported : %s\n", (isSupported ? "true" : "false")); + return isSupported; +} - switch(fontIdCacheItem.type) +const FontCacheItemInterface* FontClient::Plugin::GetCachedFontItem(FontId id) const +{ + const FontId index = id - 1u; + if((id > 0u) && (index < mFontIdCache.Count())) { - case FontDescription::FACE_FONT: + const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; + switch(fontIdCacheItem.type) { - if(fontIdCacheItem.id < mFontFaceCache.size()) + case FontDescription::FACE_FONT: { - FontFaceCacheItem& cacheItem = mFontFaceCache[fontIdCacheItem.id]; - - if(nullptr == cacheItem.mCharacterSet) - { - // Create again the character set. - // It can be null if the ResetSystemDefaults() method has been called. - - FontDescription description; - description.path = cacheItem.mPath; - description.family = std::move(FontFamily(cacheItem.mFreeTypeFace->family_name)); - description.weight = FontWeight::NONE; - description.width = FontWidth::NONE; - description.slant = FontSlant::NONE; - - // Note FreeType doesn't give too much info to build a proper font style. - if(cacheItem.mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC) - { - description.slant = FontSlant::ITALIC; - } - if(cacheItem.mFreeTypeFace->style_flags & FT_STYLE_FLAG_BOLD) - { - description.weight = FontWeight::BOLD; - } - - cacheItem.mCharacterSet = FcCharSetCopy(CreateCharacterSetFromDescription(description)); - } - - isSupported = FcCharSetHasChar(cacheItem.mCharacterSet, character); + return &mFontFaceCache[fontIdCacheItem.id]; } - break; - } - case FontDescription::BITMAP_FONT: - { - const BitmapFont& bitmapFont = mBitmapFontCache[fontIdCacheItem.id].font; - - for(const auto& glyph : bitmapFont.glyphs) + case FontDescription::BITMAP_FONT: { - if(glyph.utf32 == character) - { - isSupported = true; - break; - } + return &mBitmapFontCache[fontIdCacheItem.id]; + } + default: + { + DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid type of font\n"); } - break; - } - default: - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid type of font\n"); } } - - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " is supported : %s\n", (isSupported ? "true" : "false")); - return isSupported; + return nullptr; } FontId FontClient::Plugin::FindFontForCharacter(const FontList& fontList, @@ -1017,35 +912,7 @@ FontId FontClient::Plugin::GetFontId(const BitmapFont& bitmapFont) } } - BitmapFontCacheItem bitmapFontCacheItem; - bitmapFontCacheItem.font = bitmapFont; - bitmapFontCacheItem.id = mFontIdCache.Count(); - - // Resize the vector with the pixel buffers. - bitmapFontCacheItem.pixelBuffers.resize(bitmapFont.glyphs.size()); - - // Traverse all the glyphs and load the pixel buffer of those with ascender and descender equal to zero. - unsigned int index = 0u; - for(auto& glyph : bitmapFontCacheItem.font.glyphs) - { - Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index]; - - if(EqualsZero(glyph.ascender) && EqualsZero(glyph.descender)) - { - // Load the glyph. - pixelBuffer = LoadImageFromFile(glyph.url); - - if(pixelBuffer) - { - glyph.ascender = static_cast(pixelBuffer.GetHeight()); - } - } - - bitmapFontCacheItem.font.ascender = std::max(glyph.ascender, bitmapFontCacheItem.font.ascender); - bitmapFontCacheItem.font.descender = std::min(glyph.descender, bitmapFontCacheItem.font.descender); - - ++index; - } + BitmapFontCacheItem bitmapFontCacheItem(bitmapFont, mFontIdCache.Count()); FontIdCacheItem fontIdCacheItem; fontIdCacheItem.type = FontDescription::BITMAP_FONT; @@ -1114,82 +981,23 @@ void FontClient::Plugin::ValidateFont(const FontDescription& fontDescription, void FontClient::Plugin::GetFontMetrics(FontId fontId, FontMetrics& metrics) { - const FontId index = fontId - 1u; - - if((fontId > 0) && - (index < mFontIdCache.Count())) - { - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; - - switch(fontIdCacheItem.type) - { - case FontDescription::FACE_FONT: - { - const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id]; - - metrics = font.mMetrics; - - // Adjust the metrics if the fixed-size font should be down-scaled - if(font.mIsFixedSizeBitmap) - { - const float desiredFixedSize = static_cast(font.mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * mDpiVertical; - - if(desiredFixedSize > 0.f) - { - const float scaleFactor = desiredFixedSize / font.mFixedHeightPixels; - - metrics.ascender = metrics.ascender * scaleFactor; - metrics.descender = metrics.descender * scaleFactor; - metrics.height = metrics.height * scaleFactor; - metrics.underlinePosition = metrics.underlinePosition * scaleFactor; - metrics.underlineThickness = metrics.underlineThickness * scaleFactor; - } - } - break; - } - case FontDescription::BITMAP_FONT: - { - const BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id]; - - metrics.ascender = bitmapFontCacheItem.font.ascender; - metrics.descender = bitmapFontCacheItem.font.descender; - metrics.height = metrics.ascender - metrics.descender; - metrics.underlinePosition = bitmapFontCacheItem.font.underlinePosition; - metrics.underlineThickness = bitmapFontCacheItem.font.underlineThickness; - break; - } - default: - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid type of font\n"); - } - } - } - else + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); + if(fontCacheItem != nullptr) { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId); + fontCacheItem->GetFontMetrics(metrics, mDpiVertical); } } GlyphIndex FontClient::Plugin::GetGlyphIndex(FontId fontId, Character charcode) { - GlyphIndex glyphIndex = 0u; - const FontId index = fontId - 1u; - - if((fontId > 0u) && - (index < mFontIdCache.Count())) + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); + if(fontCacheItem != nullptr) { - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; - - if(FontDescription::FACE_FONT == fontIdCacheItem.type) - { - FT_Face ftFace = mFontFaceCache[fontIdCacheItem.id].mFreeTypeFace; - - glyphIndex = FT_Get_Char_Index(ftFace, charcode); - } + return fontCacheItem->GetGlyphIndex(charcode); } - return glyphIndex; + return 0u; } bool FontClient::Plugin::GetGlyphMetrics(GlyphInfo* array, @@ -1209,184 +1017,22 @@ bool FontClient::Plugin::GetBitmapMetrics(GlyphInfo* array, uint32_t size, bool horizontal) { - bool success(true); + bool success(false); for(unsigned int i = 0; i < size; ++i) { GlyphInfo& glyph = array[i]; - FontId index = glyph.fontId - 1u; - - if((glyph.fontId > 0u) && - (index < mFontIdCache.Count())) + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(glyph.fontId); + if(fontCacheItem != nullptr) { - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; - - switch(fontIdCacheItem.type) - { - case FontDescription::FACE_FONT: - { - const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id]; - - FT_Face ftFace = font.mFreeTypeFace; - -#ifdef FREETYPE_BITMAP_SUPPORT - // Check to see if we should be loading a Fixed Size bitmap? - if(font.mIsFixedSizeBitmap) - { - FT_Select_Size(ftFace, font.mFixedSizeIndex); ///< @todo: needs to be investigated why it's needed to select the size again. - int error = FT_Load_Glyph(ftFace, glyph.index, FT_LOAD_COLOR); - if(FT_Err_Ok == error) - { - glyph.width = font.mFixedWidthPixels; - glyph.height = font.mFixedHeightPixels; - glyph.advance = font.mFixedWidthPixels; - glyph.xBearing = 0.0f; - glyph.yBearing = font.mFixedHeightPixels; - - // Adjust the metrics if the fixed-size font should be down-scaled - const float desiredFixedSize = static_cast(font.mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * mDpiVertical; - - if(desiredFixedSize > 0.f) - { - const float scaleFactor = desiredFixedSize / font.mFixedHeightPixels; - - glyph.width = glyph.width * scaleFactor; - glyph.height = glyph.height * scaleFactor; - glyph.advance = glyph.advance * scaleFactor; - glyph.xBearing = glyph.xBearing * scaleFactor; - glyph.yBearing = glyph.yBearing * scaleFactor; - - glyph.scaleFactor = scaleFactor; - } - } - else - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetBitmapMetrics. FreeType Bitmap Load_Glyph error %d\n", error); - success = false; - } - } - else -#endif - { - // FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap. - // i.e. with the SNum-3R font. - // @todo: add an option to use the FT_LOAD_DEFAULT if required? - int error = FT_Load_Glyph(ftFace, glyph.index, FT_LOAD_NO_AUTOHINT); - - // Keep the width of the glyph before doing the software emboldening. - // It will be used to calculate a scale factor to be applied to the - // advance as Harfbuzz doesn't apply any SW emboldening to calculate - // the advance of the glyph. - const float width = static_cast(ftFace->glyph->metrics.width) * FROM_266; - - if(FT_Err_Ok == error) - { - const bool isEmboldeningRequired = glyph.isBoldRequired && !(ftFace->style_flags & FT_STYLE_FLAG_BOLD); - if(isEmboldeningRequired) - { - // Does the software bold. - FT_GlyphSlot_Embolden(ftFace->glyph); - } - - glyph.width = static_cast(ftFace->glyph->metrics.width) * FROM_266; - glyph.height = static_cast(ftFace->glyph->metrics.height) * FROM_266; - if(horizontal) - { - glyph.xBearing += static_cast(ftFace->glyph->metrics.horiBearingX) * FROM_266; - glyph.yBearing += static_cast(ftFace->glyph->metrics.horiBearingY) * FROM_266; - } - else - { - glyph.xBearing += static_cast(ftFace->glyph->metrics.vertBearingX) * FROM_266; - glyph.yBearing += static_cast(ftFace->glyph->metrics.vertBearingY) * FROM_266; - } - - if(isEmboldeningRequired && !Dali::EqualsZero(width)) - { - // If the glyph is emboldened by software, the advance is multiplied by a - // scale factor to make it slightly bigger. - glyph.advance *= (glyph.width / width); - } - - // Use the bounding box of the bitmap to correct the metrics. - // For some fonts i.e the SNum-3R the metrics need to be corrected, - // otherwise the glyphs 'dance' up and down depending on the - // font's point size. - - FT_Glyph ftGlyph; - error = FT_Get_Glyph(ftFace->glyph, &ftGlyph); - - FT_BBox bbox; - FT_Glyph_Get_CBox(ftGlyph, FT_GLYPH_BBOX_GRIDFIT, &bbox); - - const float descender = glyph.height - glyph.yBearing; - glyph.height = (bbox.yMax - bbox.yMin) * FROM_266; - glyph.yBearing = glyph.height - round(descender); - - // Created FT_Glyph object must be released with FT_Done_Glyph - FT_Done_Glyph(ftGlyph); - } - else - { - success = false; - } - } - break; - } - case FontDescription::BITMAP_FONT: - { - BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id]; - - unsigned int index = 0u; - for(auto& item : bitmapFontCacheItem.font.glyphs) - { - if(item.utf32 == glyph.index) - { - Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index]; - if(!pixelBuffer) - { - pixelBuffer = LoadImageFromFile(item.url); - } - - glyph.width = static_cast(pixelBuffer.GetWidth()); - glyph.height = static_cast(pixelBuffer.GetHeight()); - glyph.xBearing = 0.f; - glyph.yBearing = glyph.height + item.descender; - glyph.advance = glyph.width; - glyph.scaleFactor = 1.f; - break; - } - ++index; - } - - success = true; - break; - } - default: - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid type of font\n"); - } - } + success = fontCacheItem->GetGlyphMetrics(glyph, mDpiVertical, horizontal); } - else + // Check if it's an embedded image. + else if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mEmbeddedItemCache.Count())) { - // Check if it's an embedded image. - if((0u == glyph.fontId) && (0u != glyph.index) && (glyph.index <= mEmbeddedItemCache.Count())) - { - const EmbeddedItem& item = mEmbeddedItemCache[glyph.index - 1u]; - - glyph.width = static_cast(item.width); - glyph.height = static_cast(item.height); - glyph.xBearing = 0.f; - glyph.yBearing = glyph.height; - glyph.advance = glyph.width; - glyph.scaleFactor = 1.f; - } - else - { - success = false; - } + mEmbeddedItemCache[glyph.index - 1u].GetGlyphMetrics(glyph); + success = true; } } @@ -1438,219 +1084,17 @@ bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array, void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth) { - const FontId index = fontId - 1u; - - if((fontId > 0u) && - (index < mFontIdCache.Count())) + data.isColorBitmap = false; + data.isColorEmoji = false; + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); + if(fontCacheItem != nullptr) { - data.isColorBitmap = false; - data.isColorEmoji = false; - - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; - - switch(fontIdCacheItem.type) - { - case FontDescription::FACE_FONT: - { - // For the software italics. - bool isShearRequired = false; - - const FontFaceCacheItem& fontFaceCacheItem = mFontFaceCache[fontIdCacheItem.id]; - FT_Face ftFace = fontFaceCacheItem.mFreeTypeFace; - - FT_Error error; - -#ifdef FREETYPE_BITMAP_SUPPORT - // Check to see if this is fixed size bitmap - if(fontFaceCacheItem.mIsFixedSizeBitmap) - { - error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_COLOR); - } - else -#endif - { - // FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap. - // i.e. with the SNum-3R font. - // @todo: add an option to use the FT_LOAD_DEFAULT if required? - error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_NO_AUTOHINT); - } - if(FT_Err_Ok == error) - { - if(isBoldRequired && !(ftFace->style_flags & FT_STYLE_FLAG_BOLD)) - { - // Does the software bold. - FT_GlyphSlot_Embolden(ftFace->glyph); - } - - if(isItalicRequired && !(ftFace->style_flags & FT_STYLE_FLAG_ITALIC)) - { - // Will do the software italic. - isShearRequired = true; - } - - FT_Glyph glyph; - error = FT_Get_Glyph(ftFace->glyph, &glyph); - - // Convert to bitmap if necessary - if(FT_Err_Ok == error) - { - if(glyph->format != FT_GLYPH_FORMAT_BITMAP) - { - int offsetX = 0, offsetY = 0; - bool isOutlineGlyph = (glyph->format == FT_GLYPH_FORMAT_OUTLINE && outlineWidth > 0); - - // Create a bitmap for the outline - if(isOutlineGlyph) - { - // Retrieve the horizontal and vertical distance from the current pen position to the - // left and top border of the glyph bitmap for a normal glyph before applying the outline. - if(FT_Err_Ok == error) - { - FT_Glyph normalGlyph; - error = FT_Get_Glyph(ftFace->glyph, &normalGlyph); - - error = FT_Glyph_To_Bitmap(&normalGlyph, FT_RENDER_MODE_NORMAL, 0, 1); - if(FT_Err_Ok == error) - { - FT_BitmapGlyph bitmapGlyph = reinterpret_cast(normalGlyph); - - offsetX = bitmapGlyph->left; - offsetY = bitmapGlyph->top; - } - - // Created FT_Glyph object must be released with FT_Done_Glyph - FT_Done_Glyph(normalGlyph); - } - - // Now apply the outline - - // Set up a stroker - FT_Stroker stroker; - error = FT_Stroker_New(mFreeTypeLibrary, &stroker); - - if(FT_Err_Ok == error) - { - FT_Stroker_Set(stroker, outlineWidth * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); - error = FT_Glyph_StrokeBorder(&glyph, stroker, 0, 1); - - if(FT_Err_Ok == error) - { - FT_Stroker_Done(stroker); - } - else - { - DALI_LOG_ERROR("FT_Glyph_StrokeBorder Failed with error: %d\n", error); - } - } - else - { - DALI_LOG_ERROR("FT_Stroker_New Failed with error: %d\n", error); - } - } - - error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); - if(FT_Err_Ok == error) - { - FT_BitmapGlyph bitmapGlyph = reinterpret_cast(glyph); - - if(isOutlineGlyph) - { - // Calculate the additional horizontal and vertical offsets needed for the position of the outline glyph - data.outlineOffsetX = offsetX - bitmapGlyph->left - outlineWidth; - data.outlineOffsetY = bitmapGlyph->top - offsetY - outlineWidth; - } - - ConvertBitmap(data, bitmapGlyph->bitmap, isShearRequired); - } - else - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Get_Glyph Failed with error: %d\n", error); - } - } - else - { - ConvertBitmap(data, ftFace->glyph->bitmap, isShearRequired); - } - - data.isColorEmoji = fontFaceCacheItem.mIsFixedSizeBitmap; - - // Created FT_Glyph object must be released with FT_Done_Glyph - FT_Done_Glyph(glyph); - } - } - else - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Load_Glyph Failed with error: %d\n", error); - } - break; - } - case FontDescription::BITMAP_FONT: - { - BitmapFontCacheItem& bitmapFontCacheItem = mBitmapFontCache[fontIdCacheItem.id]; - - unsigned int index = 0u; - for(auto& item : bitmapFontCacheItem.font.glyphs) - { - if(item.utf32 == glyphIndex) - { - Devel::PixelBuffer& pixelBuffer = bitmapFontCacheItem.pixelBuffers[index]; - if(!pixelBuffer) - { - pixelBuffer = LoadImageFromFile(item.url); - } - - data.width = pixelBuffer.GetWidth(); - data.height = pixelBuffer.GetHeight(); - - data.isColorBitmap = bitmapFontCacheItem.font.isColorFont; - - ConvertBitmap(data, data.width, data.height, pixelBuffer.GetBuffer()); - - // Sets the pixel format. - data.format = pixelBuffer.GetPixelFormat(); - break; - } - ++index; - } - break; - } - default: - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid type of font\n"); - } - } + fontCacheItem->CreateBitmap(glyphIndex, data, outlineWidth, isItalicRequired, isBoldRequired); } - else + else if((0u != glyphIndex) && (glyphIndex <= mEmbeddedItemCache.Count())) { - if((0u != glyphIndex) && (glyphIndex <= mEmbeddedItemCache.Count())) - { - // It's an embedded item. - const EmbeddedItem& item = mEmbeddedItemCache[glyphIndex - 1u]; - - data.width = item.width; - data.height = item.height; - if(0u != item.pixelBufferId) - { - Devel::PixelBuffer pixelBuffer = mPixelBufferCache[item.pixelBufferId - 1u].pixelBuffer; - if(pixelBuffer) - { - ConvertBitmap(data, pixelBuffer.GetWidth(), pixelBuffer.GetHeight(), pixelBuffer.GetBuffer()); - - // Sets the pixel format. - data.format = pixelBuffer.GetPixelFormat(); - } - } - else - { - // Creates the output buffer - const unsigned int bufferSize = data.width * data.height * 4u; - data.buffer = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[]. - - memset(data.buffer, 0u, bufferSize); - - // Just creates a void buffer. Doesn't matter what pixel format is set as is the application code the responsible of filling it. - } - } + // It's an embedded item. + mEmbeddedItemCache[glyphIndex - 1u].CreateBitmap(mPixelBufferCache, data); } } @@ -1731,62 +1175,18 @@ const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph(PointSize26Dot6 requestedP bool FontClient::Plugin::IsColorGlyph(FontId fontId, GlyphIndex glyphIndex) { - FT_Error error = -1; - - const FontId index = fontId - 1u; - - if((fontId > 0u) && - (index < mFontIdCache.Count())) - { - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; - - switch(fontIdCacheItem.type) - { - case FontDescription::FACE_FONT: - { -#ifdef FREETYPE_BITMAP_SUPPORT - const FontFaceCacheItem& item = mFontFaceCache[fontIdCacheItem.id]; - FT_Face ftFace = item.mFreeTypeFace; - - // Check to see if this is fixed size bitmap - if(item.mHasColorTables) - { - error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_COLOR); - } -#endif - break; - } - case FontDescription::BITMAP_FONT: - { - error = FT_Err_Ok; // Will return true; - break; - } - default: - { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " Invalid type of font\n"); - } - } - } - - return FT_Err_Ok == error; + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); + return fontCacheItem && fontCacheItem->IsColorGlyph(glyphIndex); } FT_FaceRec_* FontClient::Plugin::GetFreetypeFace(FontId fontId) { - FT_Face fontFace = nullptr; - - const FontId index = fontId - 1u; - if((fontId > 0u) && - (index < mFontIdCache.Count())) + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); + if(fontCacheItem != nullptr) { - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; - - if(FontDescription::FACE_FONT == fontIdCacheItem.type) - { - fontFace = mFontFaceCache[fontIdCacheItem.id].mFreeTypeFace; - } + return fontCacheItem->GetTypeface(); } - return fontFace; + return nullptr; } FontDescription::Type FontClient::Plugin::GetFontType(FontId fontId) @@ -2165,7 +1565,7 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path, 0.0f); // Create the FreeType font face item to cache. - FontFaceCacheItem fontFaceCacheItem(ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables); + FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics, fixedSizeIndex, fixedWidth, fixedHeight, hasColorTables); // Set the index to the font's id cache. fontFaceCacheItem.mFontId = mFontIdCache.Count(); @@ -2223,7 +1623,7 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path, static_cast(ftFace->underline_thickness) * FROM_266); // Create the FreeType font face item to cache. - FontFaceCacheItem fontFaceCacheItem(ftFace, path, requestedPointSize, faceIndex, metrics); + FontFaceCacheItem fontFaceCacheItem(mFreeTypeLibrary, ftFace, path, requestedPointSize, faceIndex, metrics); // Set the index to the font's id cache. fontFaceCacheItem.mFontId = mFontIdCache.Count(); @@ -2500,28 +1900,12 @@ void FontClient::Plugin::GetFixedSizes(const FontDescription& fontDescription, bool FontClient::Plugin::HasItalicStyle(FontId fontId) const { - bool hasItalicStyle = false; - - const FontId index = fontId - 1u; - - if((fontId > 0) && - (index < mFontIdCache.Count())) - { - const FontIdCacheItem& fontIdCacheItem = mFontIdCache[index]; - - if(FontDescription::FACE_FONT == fontIdCacheItem.type) - { - const FontFaceCacheItem& font = mFontFaceCache[fontIdCacheItem.id]; - - hasItalicStyle = 0u != (font.mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC); - } - } - else + const FontCacheItemInterface* fontCacheItem = GetCachedFontItem(fontId); + if(fontCacheItem != nullptr) { - DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId); + return fontCacheItem->HasItalicStyle(); } - - return hasItalicStyle; + return false; } void FontClient::Plugin::CacheFontPath(FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path) @@ -2610,8 +1994,4 @@ void FontClient::Plugin::ClearCharacterSetFromFontFaceCache() } } -} // namespace Internal - -} // namespace TextAbstraction - -} // namespace Dali +} // namespace Dali::TextAbstraction::Internal diff --git a/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h b/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h index a8de931..6274cdf 100644 --- a/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h +++ b/dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h @@ -24,6 +24,10 @@ #include #include #include +#include +#include +#include +#include #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING #include @@ -55,11 +59,6 @@ namespace Internal typedef uint32_t FontDescriptionId; /** - * @brief Type used for indices addressing the vector with pixel buffers. - */ -typedef uint32_t PixelBufferId; - -/** * @brief Vector of character sets. */ typedef Vector<_FcCharSet*> CharacterSetList; @@ -115,42 +114,6 @@ struct FontClient::Plugin FontId fontId; ///< The font identifier. }; - /** - * @brief Caches the FreeType face and font metrics of the triplet 'path to the font file name, font point size and face index'. - */ - struct FontFaceCacheItem - { - FontFaceCacheItem(FT_Face ftFace, - const FontPath& path, - PointSize26Dot6 requestedPointSize, - FaceIndex face, - const FontMetrics& metrics); - - FontFaceCacheItem(FT_Face ftFace, - const FontPath& path, - PointSize26Dot6 requestedPointSize, - FaceIndex face, - const FontMetrics& metrics, - int fixedSizeIndex, - float fixedWidth, - float fixedHeight, - bool hasColorTables); - - FT_Face mFreeTypeFace; ///< The FreeType face. - FontPath mPath; ///< The path to the font file name. - PointSize26Dot6 mRequestedPointSize; ///< The font point size. - FaceIndex mFaceIndex; ///< The face index. - FontMetrics mMetrics; ///< The font metrics. - _FcCharSet* mCharacterSet; ///< Pointer with the range of characters. - int mFixedSizeIndex; ///< Index to the fixed size table for the requested size. - float mFixedWidthPixels; ///< The height in pixels (fixed size bitmaps only) - float mFixedHeightPixels; ///< The height in pixels (fixed size bitmaps only) - unsigned int mVectorFontId; ///< The ID of the equivalent vector-based font - FontId mFontId; ///< Index to the vector with the cache of font's ids. - bool mIsFixedSizeBitmap : 1; ///< Whether the font has fixed size bitmaps. - bool mHasColorTables : 1; ///< Whether the font has color tables. - }; - struct EllipsisItem { PointSize26Dot6 requestedPointSize; @@ -158,35 +121,6 @@ struct FontClient::Plugin }; /** - * @brief Caches pixel buffers. - */ - struct PixelBufferCacheItem - { - Devel::PixelBuffer pixelBuffer; ///< The pixel buffer loaded from the url. - std::string url; ///< The url. - }; - - /** - * @brief Caches embedded items. - */ - struct EmbeddedItem - { - PixelBufferId pixelBufferId; ///< Index to the vector of pixel buffers - unsigned int width; ///< The desired width. - unsigned int height; ///< The desired height. - }; - - /** - * @brief Stores a bitmap font and its pixel buffers per glyph. - */ - struct BitmapFontCacheItem - { - BitmapFont font; ///< The bitmap font. - std::vector pixelBuffers; ///< The pixel buffers of the glyphs. - FontId id; ///< Index to the vector with the cache of font's ids. - }; - - /** * Constructor. * * Initializes the FreeType library. @@ -255,6 +189,13 @@ struct FontClient::Plugin bool IsCharacterSupportedByFont(FontId fontId, Character character); /** + * Get the cached font item for the given font + * @param[in] id The font id to search for + * @return the matching cached font item + */ + const FontCacheItemInterface* GetCachedFontItem(FontId id) const; + + /** * @brief Finds within the @p fontList a font which support the @p carcode. * * @param[in] fontList A list of font paths, family, width, weight and slant. @@ -608,10 +549,8 @@ private: void ClearCharacterSetFromFontFaceCache(); private: - // Declared private and left undefined to avoid copies. - Plugin(const Plugin&); - // Declared private and left undefined to avoid copies. - Plugin& operator=(const Plugin&); + Plugin(const Plugin&) = delete; + Plugin& operator=(const Plugin&) = delete; private: FT_Library mFreeTypeLibrary; ///< A handle to a FreeType library instance. diff --git a/dali/internal/text/text-abstraction/plugin/font-client-utils.cpp b/dali/internal/text/text-abstraction/plugin/font-client-utils.cpp index d257d53..3f9743f 100644 --- a/dali/internal/text/text-abstraction/plugin/font-client-utils.cpp +++ b/dali/internal/text/text-abstraction/plugin/font-client-utils.cpp @@ -21,7 +21,9 @@ #include +#if defined(DEBUG_ENABLED) extern Dali::Integration::Log::Filter* gFontClientLogFilter; +#endif namespace Dali::TextAbstraction::Internal { diff --git a/dali/internal/text/text-abstraction/plugin/font-client-utils.h b/dali/internal/text/text-abstraction/plugin/font-client-utils.h index 4465521..f329193 100644 --- a/dali/internal/text/text-abstraction/plugin/font-client-utils.h +++ b/dali/internal/text/text-abstraction/plugin/font-client-utils.h @@ -25,6 +25,10 @@ #include #include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_OUTLINE_H +#include FT_STROKER_H +#include FT_SYNTHESIS_H namespace Dali::TextAbstraction::Internal { diff --git a/dali/internal/text/text-abstraction/plugin/font-face-cache-item.cpp b/dali/internal/text/text-abstraction/plugin/font-face-cache-item.cpp new file mode 100644 index 0000000..5608b03 --- /dev/null +++ b/dali/internal/text/text-abstraction/plugin/font-face-cache-item.cpp @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#if defined(DEBUG_ENABLED) +extern Dali::Integration::Log::Filter* gFontClientLogFilter; +#endif + +namespace Dali::TextAbstraction::Internal +{ +const float FROM_266 = 1.0f / 64.0f; +const float POINTS_PER_INCH = 72.f; + +FontFaceCacheItem::FontFaceCacheItem(FT_Library& freeTypeLibrary, + FT_Face ftFace, + const FontPath& path, + PointSize26Dot6 requestedPointSize, + FaceIndex face, + const FontMetrics& metrics) +: mFreeTypeLibrary(freeTypeLibrary), + mFreeTypeFace(ftFace), + mPath(path), + mRequestedPointSize(requestedPointSize), + mFaceIndex(face), + mMetrics(metrics), + mCharacterSet(nullptr), + mFixedSizeIndex(0), + mFixedWidthPixels(0.f), + mFixedHeightPixels(0.f), + mVectorFontId(0u), + mFontId(0u), + mIsFixedSizeBitmap(false), + mHasColorTables(false) +{ +} + +FontFaceCacheItem::FontFaceCacheItem(FT_Library& freeTypeLibrary, + FT_Face ftFace, + const FontPath& path, + PointSize26Dot6 requestedPointSize, + FaceIndex face, + const FontMetrics& metrics, + int fixedSizeIndex, + float fixedWidth, + float fixedHeight, + bool hasColorTables) +: mFreeTypeLibrary(freeTypeLibrary), + mFreeTypeFace(ftFace), + mPath(path), + mRequestedPointSize(requestedPointSize), + mFaceIndex(face), + mMetrics(metrics), + mCharacterSet(nullptr), + mFixedSizeIndex(fixedSizeIndex), + mFixedWidthPixels(fixedWidth), + mFixedHeightPixels(fixedHeight), + mVectorFontId(0u), + mFontId(0u), + mIsFixedSizeBitmap(true), + mHasColorTables(hasColorTables) +{ +} + +void FontFaceCacheItem::GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const +{ + metrics = mMetrics; + + // Adjust the metrics if the fixed-size font should be down-scaled + if(mIsFixedSizeBitmap) + { + const float desiredFixedSize = static_cast(mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * dpiVertical; + + if(desiredFixedSize > 0.f) + { + const float scaleFactor = desiredFixedSize / mFixedHeightPixels; + + metrics.ascender = metrics.ascender * scaleFactor; + metrics.descender = metrics.descender * scaleFactor; + metrics.height = metrics.height * scaleFactor; + metrics.underlinePosition = metrics.underlinePosition * scaleFactor; + metrics.underlineThickness = metrics.underlineThickness * scaleFactor; + } + } +} + +bool FontFaceCacheItem::GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const +{ + bool success(true); + + FT_Face ftFace = mFreeTypeFace; + +#ifdef FREETYPE_BITMAP_SUPPORT + // Check to see if we should be loading a Fixed Size bitmap? + if(mIsFixedSizeBitmap) + { + FT_Select_Size(ftFace, mFixedSizeIndex); ///< @todo: needs to be investigated why it's needed to select the size again. + int error = FT_Load_Glyph(ftFace, glyph.index, FT_LOAD_COLOR); + if(FT_Err_Ok == error) + { + glyph.width = mFixedWidthPixels; + glyph.height = mFixedHeightPixels; + glyph.advance = mFixedWidthPixels; + glyph.xBearing = 0.0f; + glyph.yBearing = mFixedHeightPixels; + + // Adjust the metrics if the fixed-size font should be down-scaled + const float desiredFixedSize = static_cast(mRequestedPointSize) * FROM_266 / POINTS_PER_INCH * dpiVertical; + + if(desiredFixedSize > 0.f) + { + const float scaleFactor = desiredFixedSize / mFixedHeightPixels; + + glyph.width = glyph.width * scaleFactor; + glyph.height = glyph.height * scaleFactor; + glyph.advance = glyph.advance * scaleFactor; + glyph.xBearing = glyph.xBearing * scaleFactor; + glyph.yBearing = glyph.yBearing * scaleFactor; + + glyph.scaleFactor = scaleFactor; + } + } + else + { + DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GetBitmapMetrics. FreeType Bitmap Load_Glyph error %d\n", error); + success = false; + } + } + else +#endif + { + // FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap. + // i.e. with the SNum-3R font. + // @todo: add an option to use the FT_LOAD_DEFAULT if required? + int error = FT_Load_Glyph(ftFace, glyph.index, FT_LOAD_NO_AUTOHINT); + + // Keep the width of the glyph before doing the software emboldening. + // It will be used to calculate a scale factor to be applied to the + // advance as Harfbuzz doesn't apply any SW emboldening to calculate + // the advance of the glyph. + const float width = static_cast(ftFace->glyph->metrics.width) * FROM_266; + + if(FT_Err_Ok == error) + { + const bool isEmboldeningRequired = glyph.isBoldRequired && !(ftFace->style_flags & FT_STYLE_FLAG_BOLD); + if(isEmboldeningRequired) + { + // Does the software bold. + FT_GlyphSlot_Embolden(ftFace->glyph); + } + + glyph.width = static_cast(ftFace->glyph->metrics.width) * FROM_266; + glyph.height = static_cast(ftFace->glyph->metrics.height) * FROM_266; + if(horizontal) + { + glyph.xBearing += static_cast(ftFace->glyph->metrics.horiBearingX) * FROM_266; + glyph.yBearing += static_cast(ftFace->glyph->metrics.horiBearingY) * FROM_266; + } + else + { + glyph.xBearing += static_cast(ftFace->glyph->metrics.vertBearingX) * FROM_266; + glyph.yBearing += static_cast(ftFace->glyph->metrics.vertBearingY) * FROM_266; + } + + if(isEmboldeningRequired && !Dali::EqualsZero(width)) + { + // If the glyph is emboldened by software, the advance is multiplied by a + // scale factor to make it slightly bigger. + glyph.advance *= (glyph.width / width); + } + + // Use the bounding box of the bitmap to correct the metrics. + // For some fonts i.e the SNum-3R the metrics need to be corrected, + // otherwise the glyphs 'dance' up and down depending on the + // font's point size. + + FT_Glyph ftGlyph; + error = FT_Get_Glyph(ftFace->glyph, &ftGlyph); + + FT_BBox bbox; + FT_Glyph_Get_CBox(ftGlyph, FT_GLYPH_BBOX_GRIDFIT, &bbox); + + const float descender = glyph.height - glyph.yBearing; + glyph.height = (bbox.yMax - bbox.yMin) * FROM_266; + glyph.yBearing = glyph.height - round(descender); + + // Created FT_Glyph object must be released with FT_Done_Glyph + FT_Done_Glyph(ftGlyph); + } + else + { + success = false; + } + } + return success; +} + +/** + * @brief Create a bitmap representation of a glyph from a face font + * + * @param[in] glyphIndex The index of a glyph within the specified font. + * @param[in] isItalicRequired Whether the glyph requires italic style. + * @param[in] isBoldRequired Whether the glyph requires bold style. + * @param[out] data The bitmap data. + * @param[in] outlineWidth The width of the glyph outline in pixels. + */ +void FontFaceCacheItem::CreateBitmap( + GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const +{ + FT_Face ftFace = mFreeTypeFace; + FT_Error error; + // For the software italics. + bool isShearRequired = false; + +#ifdef FREETYPE_BITMAP_SUPPORT + // Check to see if this is fixed size bitmap + if(mIsFixedSizeBitmap) + { + error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_COLOR); + } + else +#endif + { + // FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap. + // i.e. with the SNum-3R font. + // @todo: add an option to use the FT_LOAD_DEFAULT if required? + error = FT_Load_Glyph(ftFace, glyphIndex, FT_LOAD_NO_AUTOHINT); + } + if(FT_Err_Ok == error) + { + if(isBoldRequired && !(ftFace->style_flags & FT_STYLE_FLAG_BOLD)) + { + // Does the software bold. + FT_GlyphSlot_Embolden(ftFace->glyph); + } + + if(isItalicRequired && !(ftFace->style_flags & FT_STYLE_FLAG_ITALIC)) + { + // Will do the software italic. + isShearRequired = true; + } + + FT_Glyph glyph; + error = FT_Get_Glyph(ftFace->glyph, &glyph); + + // Convert to bitmap if necessary + if(FT_Err_Ok == error) + { + if(glyph->format != FT_GLYPH_FORMAT_BITMAP) + { + int offsetX = 0, offsetY = 0; + bool isOutlineGlyph = (glyph->format == FT_GLYPH_FORMAT_OUTLINE && outlineWidth > 0); + + // Create a bitmap for the outline + if(isOutlineGlyph) + { + // Retrieve the horizontal and vertical distance from the current pen position to the + // left and top border of the glyph bitmap for a normal glyph before applying the outline. + if(FT_Err_Ok == error) + { + FT_Glyph normalGlyph; + error = FT_Get_Glyph(ftFace->glyph, &normalGlyph); + + error = FT_Glyph_To_Bitmap(&normalGlyph, FT_RENDER_MODE_NORMAL, 0, 1); + if(FT_Err_Ok == error) + { + FT_BitmapGlyph bitmapGlyph = reinterpret_cast(normalGlyph); + + offsetX = bitmapGlyph->left; + offsetY = bitmapGlyph->top; + } + + // Created FT_Glyph object must be released with FT_Done_Glyph + FT_Done_Glyph(normalGlyph); + } + + // Now apply the outline + + // Set up a stroker + FT_Stroker stroker; + error = FT_Stroker_New(mFreeTypeLibrary, &stroker); + + if(FT_Err_Ok == error) + { + FT_Stroker_Set(stroker, outlineWidth * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); + error = FT_Glyph_StrokeBorder(&glyph, stroker, 0, 1); + + if(FT_Err_Ok == error) + { + FT_Stroker_Done(stroker); + } + else + { + DALI_LOG_ERROR("FT_Glyph_StrokeBorder Failed with error: %d\n", error); + } + } + else + { + DALI_LOG_ERROR("FT_Stroker_New Failed with error: %d\n", error); + } + } + + error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); + if(FT_Err_Ok == error) + { + FT_BitmapGlyph bitmapGlyph = reinterpret_cast(glyph); + + if(isOutlineGlyph) + { + // Calculate the additional horizontal and vertical offsets needed for the position of the outline glyph + data.outlineOffsetX = offsetX - bitmapGlyph->left - outlineWidth; + data.outlineOffsetY = bitmapGlyph->top - offsetY - outlineWidth; + } + + ConvertBitmap(data, bitmapGlyph->bitmap, isShearRequired); + } + else + { + DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Get_Glyph Failed with error: %d\n", error); + } + } + else + { + ConvertBitmap(data, ftFace->glyph->bitmap, isShearRequired); + } + + data.isColorEmoji = mIsFixedSizeBitmap; + + // Created FT_Glyph object must be released with FT_Done_Glyph + FT_Done_Glyph(glyph); + } + } + else + { + DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Load_Glyph Failed with error: %d\n", error); + } +} + +bool FontFaceCacheItem::IsColorGlyph(GlyphIndex glyphIndex) const +{ + FT_Error error = -1; + +#ifdef FREETYPE_BITMAP_SUPPORT + // Check to see if this is fixed size bitmap + if(mHasColorTables) + { + error = FT_Load_Glyph(mFreeTypeFace, glyphIndex, FT_LOAD_COLOR); + } +#endif + return FT_Err_Ok == error; +} + +/** + * Check if the character is supported by this font + * @param[in] character The character to test + */ +bool FontFaceCacheItem::IsCharacterSupported(Character character) +{ + if(nullptr == mCharacterSet) + { + // Create again the character set. + // It can be null if the ResetSystemDefaults() method has been called. + + FontDescription description; + description.path = mPath; + description.family = std::move(FontFamily(mFreeTypeFace->family_name)); + description.weight = FontWeight::NONE; + description.width = FontWidth::NONE; + description.slant = FontSlant::NONE; + + // Note FreeType doesn't give too much info to build a proper font style. + if(mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC) + { + description.slant = FontSlant::ITALIC; + } + if(mFreeTypeFace->style_flags & FT_STYLE_FLAG_BOLD) + { + description.weight = FontWeight::BOLD; + } + + mCharacterSet = FcCharSetCopy(CreateCharacterSetFromDescription(description)); + } + + return FcCharSetHasChar(mCharacterSet, character); +} + +GlyphIndex FontFaceCacheItem::GetGlyphIndex(Character character) const +{ + return FT_Get_Char_Index(mFreeTypeFace, character); +} + +} // namespace Dali::TextAbstraction::Internal diff --git a/dali/internal/text/text-abstraction/plugin/font-face-cache-item.h b/dali/internal/text/text-abstraction/plugin/font-face-cache-item.h new file mode 100644 index 0000000..4a13d32 --- /dev/null +++ b/dali/internal/text/text-abstraction/plugin/font-face-cache-item.h @@ -0,0 +1,132 @@ +#ifndef DALI_TEST_ABSTRACTION_INTERNAL_FONT_FACE_CACHE_ITEM_H +#define DALI_TEST_ABSTRACTION_INTERNAL_FONT_FACE_CACHE_ITEM_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// INTERNAL INCLUDES + +#include + +// EXTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_OUTLINE_H +#include FT_STROKER_H +#include FT_SYNTHESIS_H + +namespace Dali::TextAbstraction::Internal +{ +/** + * @brief Caches the FreeType face and font metrics of the triplet 'path to the font file name, font point size and face index'. + */ +struct FontFaceCacheItem : public FontCacheItemInterface +{ + FontFaceCacheItem(FT_Library& freeTypeLibrary, + FT_Face ftFace, + const FontPath& path, + PointSize26Dot6 requestedPointSize, + FaceIndex face, + const FontMetrics& metrics); + + FontFaceCacheItem(FT_Library& freeTypeLibrary, + FT_Face ftFace, + const FontPath& path, + PointSize26Dot6 requestedPointSize, + FaceIndex face, + const FontMetrics& metrics, + int fixedSizeIndex, + float fixedWidth, + float fixedHeight, + bool hasColorTables); + + /** + * @copydoc FontCacheItemInterface::GetFontMetrics() + */ + void GetFontMetrics(FontMetrics& metrics, unsigned int dpiVertical) const override; + + /** + * @copydoc FontCacheItemInterface::GetGlyphMetrics() + */ + bool GetGlyphMetrics(GlyphInfo& glyph, unsigned int dpiVertical, bool horizontal) const override; + + /** + * @copydoc FontCacheItemInterface::CreateBitmap() + */ + void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const override; + + /** + * @copydoc FontCacheItemInterface::IsColorGlyph() + */ + bool IsColorGlyph(GlyphIndex glyphIndex) const override; + + /** + * @copydoc FontCacheItemInterface::IsCharacterSupported() + */ + bool IsCharacterSupported(Character character) override; + + /** + * @copydoc FontCacheItemInterface::GetPointSize() + */ + PointSize26Dot6 GetPointSize() const override + { + return mRequestedPointSize; + } + + /** + * @copydoc FontCacheItemInterface::GetGlyphIndex() + */ + GlyphIndex GetGlyphIndex(Character character) const override; + + /** + * @copydoc FontCacheItemInterface::GetTypeface() + */ + FT_Face GetTypeface() const override + { + return mFreeTypeFace; + } + + /** + * @copydoc FontCacheItemInterface::HasItalicStyle() + */ + bool HasItalicStyle() const override + { + return (0u != (mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC)); + } + + FT_Library& mFreeTypeLibrary; ///< A handle to a FreeType library instance. + FT_Face mFreeTypeFace; ///< The FreeType face. + FontPath mPath; ///< The path to the font file name. + PointSize26Dot6 mRequestedPointSize; ///< The font point size. + FaceIndex mFaceIndex; ///< The face index. + FontMetrics mMetrics; ///< The font metrics. + _FcCharSet* mCharacterSet; ///< Pointer with the range of characters. + int mFixedSizeIndex; ///< Index to the fixed size table for the requested size. + float mFixedWidthPixels; ///< The height in pixels (fixed size bitmaps only) + float mFixedHeightPixels; ///< The height in pixels (fixed size bitmaps only) + unsigned int mVectorFontId; ///< The ID of the equivalent vector-based font + FontId mFontId; ///< Index to the vector with the cache of font's ids. + bool mIsFixedSizeBitmap : 1; ///< Whether the font has fixed size bitmaps. + bool mHasColorTables : 1; ///< Whether the font has color tables. +}; + +} // namespace Dali::TextAbstraction::Internal + +#endif //DALI_TEST_ABSTRACTION_INTERNAL_FONT_FACE_CACHE_ITEM_H diff --git a/dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h b/dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h new file mode 100644 index 0000000..28086b6 --- /dev/null +++ b/dali/internal/text/text-abstraction/plugin/pixel-buffer-cache-item.h @@ -0,0 +1,38 @@ +#ifndef DALI_INTERNAL_TEXT_ABSTRACTION_PLUGIN_PIXEL_BUFFER_CACHE_ITEM_H +#define DALI_INTERNAL_TEXT_ABSTRACTION_PLUGIN_PIXEL_BUFFER_CACHE_ITEM_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Dali::TextAbstraction::Internal +{ +/** + * @brief Type used for indices addressing the vector with pixel buffers. + */ +typedef uint32_t PixelBufferId; + +/** + * @brief Caches pixel buffers. + */ +struct PixelBufferCacheItem +{ + Devel::PixelBuffer pixelBuffer; ///< The pixel buffer loaded from the url. + std::string url; ///< The url. +}; + +} // namespace Dali::TextAbstraction::Internal + +#endif //DALI_INTERNAL_TEXT_ABSTRACTION_PLUGIN_PIXEL_BUFFER_CACHE_ITEM_H -- 2.7.4