1 /* 2 * Copyright © 2022 Behdad Esfahbod 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 */ 24 25 #ifndef HB_PAINT_EXTENTS_HH 26 #define HB_PAINT_EXTENTS_HH 27 28 #include "hb.hh" 29 #include "hb-paint.h" 30 31 #include "hb-geometry.hh" 32 33 34 typedef struct hb_paint_extents_context_t hb_paint_extents_context_t; 35 36 struct hb_paint_extents_context_t 37 { hb_paint_extents_context_thb_paint_extents_context_t38 hb_paint_extents_context_t () 39 { 40 transforms.push (hb_transform_t{}); 41 clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED}); 42 groups.push (hb_bounds_t{hb_bounds_t::EMPTY}); 43 } 44 get_extentshb_paint_extents_context_t45 hb_extents_t get_extents () 46 { 47 return groups.tail().extents; 48 } 49 is_boundedhb_paint_extents_context_t50 bool is_bounded () 51 { 52 return groups.tail().status != hb_bounds_t::UNBOUNDED; 53 } 54 push_transformhb_paint_extents_context_t55 void push_transform (const hb_transform_t &trans) 56 { 57 hb_transform_t t = transforms.tail (); 58 t.multiply (trans); 59 transforms.push (t); 60 } 61 pop_transformhb_paint_extents_context_t62 void pop_transform () 63 { 64 transforms.pop (); 65 } 66 push_cliphb_paint_extents_context_t67 void push_clip (hb_extents_t extents) 68 { 69 /* Transform extents and push a new clip. */ 70 const hb_transform_t &t = transforms.tail (); 71 t.transform_extents (extents); 72 73 auto bounds = hb_bounds_t {extents}; 74 bounds.intersect (clips.tail ()); 75 76 clips.push (bounds); 77 } 78 pop_cliphb_paint_extents_context_t79 void pop_clip () 80 { 81 clips.pop (); 82 } 83 push_grouphb_paint_extents_context_t84 void push_group () 85 { 86 groups.push (hb_bounds_t {hb_bounds_t::EMPTY}); 87 } 88 pop_grouphb_paint_extents_context_t89 void pop_group (hb_paint_composite_mode_t mode) 90 { 91 const hb_bounds_t src_bounds = groups.pop (); 92 hb_bounds_t &backdrop_bounds = groups.tail (); 93 94 // https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite 95 switch ((int) mode) 96 { 97 case HB_PAINT_COMPOSITE_MODE_CLEAR: 98 backdrop_bounds.status = hb_bounds_t::EMPTY; 99 break; 100 case HB_PAINT_COMPOSITE_MODE_SRC: 101 case HB_PAINT_COMPOSITE_MODE_SRC_OUT: 102 backdrop_bounds = src_bounds; 103 break; 104 case HB_PAINT_COMPOSITE_MODE_DEST: 105 case HB_PAINT_COMPOSITE_MODE_DEST_OUT: 106 break; 107 case HB_PAINT_COMPOSITE_MODE_SRC_IN: 108 case HB_PAINT_COMPOSITE_MODE_DEST_IN: 109 backdrop_bounds.intersect (src_bounds); 110 break; 111 default: 112 backdrop_bounds.union_ (src_bounds); 113 break; 114 } 115 } 116 painthb_paint_extents_context_t117 void paint () 118 { 119 const hb_bounds_t &clip = clips.tail (); 120 hb_bounds_t &group = groups.tail (); 121 122 group.union_ (clip); 123 } 124 125 protected: 126 hb_vector_t<hb_transform_t> transforms; 127 hb_vector_t<hb_bounds_t> clips; 128 hb_vector_t<hb_bounds_t> groups; 129 }; 130 131 HB_INTERNAL hb_paint_funcs_t * 132 hb_paint_extents_get_funcs (); 133 134 135 #endif /* HB_PAINT_EXTENTS_HH */ 136