From 6bd549e8df66cc450b40cf26ef56f0ae5d8f37de Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 17 Jun 2022 21:54:30 +0930 Subject: [PATCH 1/3] Add color mode option --- src/cairo-font-options.c | 50 ++++++++++++++++++++++++++++++++++++++- src/cairo-ft-font.c | 12 +++++++++- src/cairo-surface.c | 4 +++- src/cairo-types-private.h | 1 + src/cairo.h | 30 +++++++++++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c index 73a1c6b75..30d695894 100644 --- a/src/cairo-font-options.c +++ b/src/cairo-font-options.c @@ -57,6 +57,7 @@ static const cairo_font_options_t _cairo_font_options_nil = { CAIRO_HINT_METRICS_DEFAULT, CAIRO_ROUND_GLYPH_POS_DEFAULT, NULL, /* variations */ + CAIRO_COLOR_MODE_DEFAULT, CAIRO_COLOR_PALETTE_DEFAULT }; @@ -76,6 +77,7 @@ _cairo_font_options_init_default (cairo_font_options_t *options) options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT; options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT; options->variations = NULL; + options->color_mode = CAIRO_COLOR_MODE_DEFAULT; options->palette_index = CAIRO_COLOR_PALETTE_DEFAULT; } @@ -90,6 +92,7 @@ _cairo_font_options_init_copy (cairo_font_options_t *options, options->hint_metrics = other->hint_metrics; options->round_glyph_positions = other->round_glyph_positions; options->variations = other->variations ? strdup (other->variations) : NULL; + options->color_mode = other->color_mode; options->palette_index = other->palette_index; } @@ -259,6 +262,8 @@ cairo_font_options_merge (cairo_font_options_t *options, } } + if (other->color_mode != CAIRO_COLOR_MODE_DEFAULT) + options->color_mode = other->color_mode; if (other->palette_index != CAIRO_COLOR_PALETTE_DEFAULT) options->palette_index = other->palette_index; } @@ -298,6 +303,7 @@ cairo_font_options_equal (const cairo_font_options_t *options, ((options->variations == NULL && other->variations == NULL) || (options->variations != NULL && other->variations != NULL && strcmp (options->variations, other->variations) == 0)) && + options->color_mode == other->color_mode && options->palette_index == other->palette_index); } slim_hidden_def (cairo_font_options_equal); @@ -333,7 +339,8 @@ cairo_font_options_hash (const cairo_font_options_t *options) (options->subpixel_order << 4) | (options->lcd_filter << 8) | (options->hint_style << 12) | - (options->hint_metrics << 16)) ^ hash; + (options->hint_metrics << 16) | + (options->color_mode << 20)) ^ hash; } slim_hidden_def (cairo_font_options_hash); @@ -631,6 +638,47 @@ cairo_font_options_get_variations (cairo_font_options_t *options) return options->variations; } +/** + * cairo_font_options_set_color_mode: + * @options: a #cairo_font_options_t + * @font_color: the new color mode + * + * Sets the color mode for the font options object. This controls + * whether color fonts are to be rendered in color or as outlines. + * See the documentation for #cairo_color_mode_t for full details. + * + * Since: 1.18 + **/ +cairo_public void +cairo_font_options_set_color_mode (cairo_font_options_t *options, + cairo_color_mode_t color_mode) +{ + if (cairo_font_options_status (options)) + return; + + options->color_mode = color_mode; +} + +/** + * cairo_font_options_get_color_mode: + * @options: a #cairo_font_options_t + * + * Gets the color mode for the font options object. + * See the documentation for #cairo_color_mode_t for full details. + * + * Return value: the color mode for the font options object + * + * Since: 1.18 + **/ +cairo_public cairo_color_mode_t +cairo_font_options_get_color_mode (const cairo_font_options_t *options) +{ + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return CAIRO_COLOR_MODE_DEFAULT; + + return options->color_mode; +} + /** * cairo_font_options_set_color_palette: * @options: a #cairo_font_options_t diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 41a9a8321..cdb02ff65 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -2664,10 +2664,20 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; + /* The font metrics for color glyphs should be the same as the + * outline glyphs. But just in case there aren't, request the + * color or outline metrics based on the font option and if + * the font has color. + */ + int color_flag = 0; +#ifdef FT_LOAD_COLOR + if (unscaled->have_color && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) + color_flag = FT_LOAD_COLOR; +#endif status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, scaled_glyph, face, - load_flags, + load_flags | color_flag, !hint_metrics, vertical_layout); if (unlikely (status)) diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 0bc0b8c7d..105f4bff1 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -2901,7 +2901,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, if (unlikely (status)) return status; - if (_cairo_scaled_font_has_color_glyphs (scaled_font)) { + if (_cairo_scaled_font_has_color_glyphs (scaled_font) && + scaled_font->options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) + { utf8_copy = malloc (sizeof (char) * utf8_len); memcpy (utf8_copy, utf8, sizeof (char) * utf8_len); utf8 = utf8_copy; diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h index f01afcf2d..a9980f3b9 100644 --- a/src/cairo-types-private.h +++ b/src/cairo-types-private.h @@ -195,6 +195,7 @@ struct _cairo_font_options { cairo_hint_metrics_t hint_metrics; cairo_round_glyph_positions_t round_glyph_positions; char *variations; + cairo_color_mode_t color_mode; unsigned int palette_index; }; diff --git a/src/cairo.h b/src/cairo.h index aec16eaed..82e2c69d8 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -1369,6 +1369,29 @@ typedef enum _cairo_hint_metrics { CAIRO_HINT_METRICS_ON } cairo_hint_metrics_t; +/** + * cairo_color_mode_t: + * @CAIRO_COLOR_MODE_DEFAULT: Use the default color mode for + * font backend and target device, since 1.18. + * @CAIRO_COLOR_MODE_NO_COLOR: Disable rendering color glyphs. Glyphs are + * always rendered as outline glyphs, since 1.18. + * @CAIRO_COLOR_MODE_COLOR: Enable rendering color glyphs. If the font + * contains a color presentation for a glyph, and when supported by + * the font backend, the glyph will be rendered in color, since 1.18. + * + * Specifies if color fonts are to be rendered using the the color + * glyphs or outline glyphs. Glyphs that do not have a color + * presentation, and non-color fonts are not affected by this font + * option. + * + * Since: 1.18 + **/ +typedef enum _cairo_color_mode { + CAIRO_COLOR_MODE_DEFAULT, + CAIRO_COLOR_MODE_NO_COLOR, + CAIRO_COLOR_MODE_COLOR +} cairo_color_mode_t; + /** * cairo_font_options_t: * @@ -1448,6 +1471,13 @@ cairo_font_options_set_variations (cairo_font_options_t *options, #define CAIRO_COLOR_PALETTE_DEFAULT 0 +cairo_public void +cairo_font_options_set_color_mode (cairo_font_options_t *options, + cairo_color_mode_t color_mode); + +cairo_public cairo_color_mode_t +cairo_font_options_get_color_mode (const cairo_font_options_t *options); + cairo_public unsigned int cairo_font_options_get_color_palette (const cairo_font_options_t *options); From 99d59f00d649c2b347f41e6e24fb0ddb2abb077b Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sat, 18 Jun 2022 05:59:38 +0930 Subject: [PATCH 2/3] Test color_mode option in ft-color-font test --- test/ft-color-font.c | 20 +++++++++++++----- test/reference/ft-color-font.image16.ref.png | Bin 1151 -> 887 bytes test/reference/ft-color-font.pdf.ref.png | Bin 0 -> 1191 bytes .../reference/ft-color-font.recording.ref.png | Bin 1655 -> 1824 bytes test/reference/ft-color-font.ref.png | Bin 1578 -> 1813 bytes test/reference/ft-color-font.script.xfail.png | Bin 2015 -> 2529 bytes 6 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 test/reference/ft-color-font.pdf.ref.png diff --git a/test/ft-color-font.c b/test/ft-color-font.c index 58a1dc3ca..d10555dcf 100644 --- a/test/ft-color-font.c +++ b/test/ft-color-font.c @@ -27,9 +27,9 @@ #include "cairo-test.h" #include -#define WIDTH 50 -#define HEIGHT WIDTH - +#define SIZE 40 +#define HEIGHT SIZE +#define WIDTH (SIZE * 1.5) #define FONT "Noto Color Emoji" static const char smiley_face_utf8[] = { 0xf0, 0x9f, 0x99, 0x82, 0x00 }; /* U+1F642 */ @@ -87,13 +87,23 @@ static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_test_status_t result; + cairo_font_options_t *font_options; result = set_color_emoji_font (cr); if (result != CAIRO_TEST_SUCCESS) return result; - cairo_set_font_size (cr, HEIGHT/2); - cairo_move_to (cr, width/4, 3*height/4); + cairo_set_font_size (cr, SIZE/2); + cairo_move_to (cr, SIZE/8, 0.7 * SIZE); + + cairo_show_text(cr, smiley_face_utf8); + + /* Show that the color mode font option can disable color rendering */ + font_options = cairo_font_options_create (); + cairo_get_font_options (cr, font_options); + cairo_font_options_set_color_mode (font_options, CAIRO_COLOR_MODE_NO_COLOR); + cairo_set_font_options (cr, font_options); + cairo_font_options_destroy (font_options); cairo_show_text(cr, smiley_face_utf8); diff --git a/test/reference/ft-color-font.image16.ref.png b/test/reference/ft-color-font.image16.ref.png index 579cd69c9ea76d2f2313d7205fd02a9e41a3d3f9..8c7463420b2f8dc368d7b837d6fd74f929687152 100644 GIT binary patch delta 882 zcmV-&1C9Lu2=@jdiBL{Q4GJ0x0000DNk~Le0000y0000e2m$~A04>=LsF5KQe*-K@ zL_t(oh3%J5XdG1-z<+LD!Z)~qS=hh~Y{UVT1k9mDp%E%%p$8)<9-ADudJridq=y`O z=%E)+(t@WwsE6JP{vnq_3SDduf(nbQ7;p|*+=VR8)GYR+JQok$-AUSsNzuuAm>-W} z_;?JzdGpQpz6UuuIXO8wIq=L=f6O&_EK?71qt(mZlS!CEr57t~T@BpI$ap;VW0Ro|X#E&fe>b{u_Uk>B z9yWY+$qQbZm1n_#zzobl0cQ5u8z?{l2AC;Iu2V90^ZU%L3#rkySLD>oj?9jX4GI`R z1Tz{UL+|l$sGTbXUe?ZsNUyKB6ceX=O|8A(xo|PmezJu{PFaHV!u zCLk?_*OnZnlQh`6{lGDVf7{yHPNX+)MUIg$)K*iIY;mYAO+q^Gkm7*?=lO&?iou^t zg#39Y+=(%G6&b&tKv0p#|JVPTl*hY8!R*UdSU+F#J;(R(Dv9*kJK`37-y?WY7?)^+ z2(A$KPgeR#L}c}iCqBAK3!Vrm=@Iu8t1zm;M`91$YhSZ2)hW_pe-~ABtYSem?xl%X zx?KfLc6A7M^jNR@FG$&3?10x7BzVp-Q&0ed{>g`zJI$YTy71Sm0|VRp&E9GBKl!w? z7unNG4iCY?L+pL6f75IHlC5<5HokU7>Kney$#`>#mHOw=*6mpBuwnA%Wc_?;bw#kC zk3Ih9V~CVa%%l#sIXO8wIsb3|24cuC?&7pFGynhq07*qo IM6N<$f|3%g^8f$< delta 1148 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 O0000pdVDk2iSgSP+MDKv@z0<$F!!I%yeG& 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 literal 1578 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 literal 2015 zcmV<52O#)~P)p&p7NfZ!lD-<@V+vo&rpjKMDAqs_3)DBuy7$f~6quC}18y{l=1XC#=!Nzgy*ohs- ziC=6#`@OqA?9dci)#PK+B>yDqN!C5*p5Oc3bI&;s$RURua>yZv9CFAZhaCRTK!(zJ zb$p7V<9A1t`)Woi{a3FjLYFQQK@jlW&0CVi)8~u3+lu4cRWGLoV=u*EIOz+qM<6pp zv$U`Hn+mQiUZ4@`7P6$5HiKm?$7IHL6x)T%atFT zj_H=H3r@VbS?JH+gF+-FiX?A;r(ti{RdjpNEKcQVBJma{(E{l5xd;b9*JphcX)=1V zoeBU{>1mklN z6#yd-MBHw|_gT*X$hX;O)aN2G04xAK-vr;n3U1dQ-ZFZpwJ`vK4->=yx074Q_+iWx-0_<=*4U0hG^jdj% z{lAl@(aZfaXJ78lHjV))a&`V8-ZkNoqT3^j6#heL60FZf%6LHXxd{_$CJX>2fMCFL z@1+?{7McPO1Hf8g8ea#s(%dw~G7qGnE&lr$aq9jA206+-U|>_c;07B-(i_Is4%Dz@qaNts%Kl z{3?5)@VTBvw?6Rg?H(J51ZK!39AM(pmqVA+Nj$H=!mhb=TpMZiW_A4gP2`O;KUH7d zw3hRqs%NwS3`i%n0l*u=%??lZBdSS%U76U)Zh0VSWyV4iFRl%rKW)~GyCVp7H&PL8 zAA19Ul&6W9zCT*M?Y9bcNQs26Us82_@+U?MK*s}G9?)_?%->AT-&vgcMeFg%u*v)7 zD`e*bm0P8sDtn*!T>NGDcqAAC6yN?&GUjh41}^O<=yMSr4}7-u=j`KK=M629%lr28 z(ybdL*y1F?yDq}xi`(hPHjPTII4S|a)Bbtt2VR2rFnesuqr867QOQ^Yd`GaTdu@C3 zDCl$&=SOwSrTtU6`|SsnNX-vc5FOH2DhD8#sTDkc`3Y-Lv162RLe1);bvA3!{kB>y zu)g!vQmy6v!m?o}OU9?_^}W|~(CxmL6OpD{WWubaS>;H-uV3$lvjjYV17H510}zXy zWoq-!=0n&A`D^S=y2I?#x-tU*#G)RkwU&F8oChFho;UKUzs|*%&~HWBk)Yyz_fc=L z>kpEBo?_;gUonzy+HrAciBv87QBpH<6g4^=Gzq|Hv(es){jg;E2H)#P1n|Vhm!zuA zs;u1gn@EgGqU3m#iXxyNZl_VCNr(W5zFKalt%>9}grHDbXjqjW*B4r-kg<;fFb=m< zW4VJy5C1DZc|*t0Dq=hC>M^ceFDXV;P(cL3BA_?hsJhfj+vOQ@<&E~h^6RHtFGv3o zmHA(#6iN$K>nt>pve3@df#k)+n#h>OdEQN-%8o>ym8wgvRBg7=aK@KrLJe5dTdY(rwNfwADoABtD8V`$bWF+IXlb|XTe|bWH}2mTgEH#+KD$OS6^7Ah_^V20qIWG0D$AaV$>DWPqo=j!vL()Yh`xrr=0tvx3|4J)*D^& z`!``2W_{?dDTDr9>*A4vq~34QoLju7;KYfSHM?d##`WB3BEc5ty}k714!WV?eDbNv zl|5ZkI=c4F-WRQQt;woh{LitzrJ1=ovxeE`Yf$_%{tIaKKSMXWwG;pV002ovPDHLkV1i~K;>Z91 From cdb7c298c7b89307ad69b94a1126221bd7c06579 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sat, 18 Jun 2022 12:50:24 +0930 Subject: [PATCH 3/3] svg: Fix invalid output when image size is 0x0 cairo_surface_write_to_png_stream fails if width or height is 0 --- src/cairo-svg-surface.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index dfb72b2ad..b39a94a37 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -2118,24 +2118,28 @@ _cairo_svg_surface_emit_surface (cairo_svg_document_t *document, assert (is_bounded); _cairo_svg_stream_printf (&document->xml_node_defs, - "xml_node_defs, - uri, uri_len); - } else { - status = _cairo_surface_base64_encode (surface, - &document->xml_node_defs); - if (unlikely (status)) - return status; + if (extents.width != 0 && extents.height != 0) { + _cairo_svg_stream_printf (&document->xml_node_defs, " xlink:href=\""); + cairo_surface_get_mime_data (surface, CAIRO_MIME_TYPE_URI, + &uri, &uri_len); + if (uri != NULL) { + _cairo_svg_surface_emit_attr_value (&document->xml_node_defs, + uri, uri_len); + } else { + status = _cairo_surface_base64_encode (surface, + &document->xml_node_defs); + if (unlikely (status)) + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "\""); } - _cairo_svg_stream_printf (&document->xml_node_defs, "\"/>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "/>\n"); return CAIRO_STATUS_SUCCESS; }