5 #include <boost/shared_ptr.hpp>
6 #include "xy_overlay_paint_machine.h"
7 #include "xy_clipper_paint_machine.h"
11 //////////////////////////////////////////////////////////////////////////
15 CRect
DrawItem::GetDirtyRect()
18 if(!switchpts
|| !fBody
&& !fBorder
) return(r
);
20 ASSERT(overlay_paint_machine
);
21 CRect overlay_rect
= overlay_paint_machine
->CalcDirtyRect();
23 // Remember that all subtitle coordinates are specified in 1/8 pixels
24 // (x+4)>>3 rounds to nearest whole pixel.
25 // ??? What is xsub, ysub, mOffsetX and mOffsetY ?
26 int x
= (xsub
+ overlay_rect
.left
+ 4)>>3;
27 int y
= (ysub
+ overlay_rect
.top
+ 4)>>3;
28 int w
= overlay_rect
.Width()>>3;
29 int h
= overlay_rect
.Height()>>3;
30 r
= clip_rect
& CRect(x
, y
, x
+w
, y
+h
);
31 r
&= clipper
->CalcDirtyRect();
35 CRect
DrawItem::Draw( SubPicDesc
& spd
, DrawItem
& draw_item
, const CRect
& clip_rect
)
38 SharedPtrGrayImage2 alpha_mask
;
39 draw_item
.clipper
->Paint(&alpha_mask
);
41 SharedPtrOverlay overlay
;
42 ASSERT(draw_item
.overlay_paint_machine
);
43 draw_item
.overlay_paint_machine
->Paint(&overlay
);
45 const SharedPtrByte
& alpha
= Rasterizer::CompositeAlphaMask(spd
, overlay
, draw_item
.clip_rect
& clip_rect
, alpha_mask
.get(),
46 draw_item
.xsub
, draw_item
.ysub
, draw_item
.switchpts
, draw_item
.fBody
, draw_item
.fBorder
,
48 Rasterizer::Draw(spd
, overlay
, result
, alpha
.get(),
49 draw_item
.xsub
, draw_item
.ysub
, draw_item
.switchpts
, draw_item
.fBody
, draw_item
.fBorder
);
53 DrawItem
* DrawItem::CreateDrawItem( const SharedPtrOverlayPaintMachine
& overlay_paint_machine
, const CRect
& clipRect
,
54 const SharedPtrCClipperPaintMachine
&clipper
, int xsub
, int ysub
, const DWORD
* switchpts
, bool fBody
, bool fBorder
)
56 DrawItem
* result
= new DrawItem();
57 result
->overlay_paint_machine
= overlay_paint_machine
;
58 result
->clip_rect
= clipRect
;
59 result
->clipper
= clipper
;
63 memcpy(result
->switchpts
, switchpts
, sizeof(result
->switchpts
));
64 result
->fBody
= fBody
;
65 result
->fBorder
= fBorder
;
69 //////////////////////////////////////////////////////////////////////////
74 CRect
CompositeDrawItem::GetDirtyRect( CompositeDrawItem
& item
)
79 result
|= item
.shadow
->GetDirtyRect();
83 result
|= item
.outline
->GetDirtyRect();
87 result
|= *item
.body
->GetDirtyRect();
92 struct GroupedDrawItems
94 CAtlList
<SharedPtrDrawItem
> draw_item_list
;
98 //temporary data struct for the complex dirty rect splitting and draw item grouping algorithm
99 struct CompositeDrawItemEx
101 CompositeDrawItem
*item
;
102 CAtlList
<int> rect_id_list
;
106 typedef CAtlList
<CompositeDrawItemEx
*> PCompositeDrawItemExList
;
107 typedef CAtlArray
<CompositeDrawItemEx
> CompositeDrawItemExVec
;
108 typedef CAtlArray
<CompositeDrawItemExVec
> CompositeDrawItemExTree
;
110 typedef ::boost::shared_ptr
<PCompositeDrawItemExList
> SharedPCompositeDrawItemExList
;
112 class XyRectEx
: public CRect
115 SharedPCompositeDrawItemExList item_ex_list
;
117 void SetRect(const RECT
& rect
)
119 __super::operator=(rect
);
127 __super::SetRect(x1
,y1
,x2
,y2
);
131 typedef CAtlList
<XyRectEx
> XyRectExList
;
133 void MergeRects(const XyRectExList
& input
, XyRectExList
* output
);
134 void CreateDrawItemExTree( CompositeDrawItemListList
& input
,
135 CompositeDrawItemExTree
*out_draw_item_ex_tree
,
136 XyRectExList
*out_rect_ex_list
);
138 void CompositeDrawItem::Draw( SubPicDesc
& spd
, CompositeDrawItemListList
& compDrawItemListList
)
140 CompositeDrawItemExTree draw_item_ex_tree
;
141 XyRectExList rect_ex_list
;
142 CreateDrawItemExTree(compDrawItemListList
, &draw_item_ex_tree
, &rect_ex_list
);
144 XyRectExList grouped_rect_exs
;
145 MergeRects(rect_ex_list
, &grouped_rect_exs
);
147 CAtlArray
<GroupedDrawItems
> grouped_draw_items
;
149 grouped_draw_items
.SetCount(grouped_rect_exs
.GetCount());
151 POSITION pos
= grouped_rect_exs
.GetHeadPosition();
152 for(int rect_id
=0;pos
;rect_id
++)
154 XyRectEx
& item
= grouped_rect_exs
.GetNext(pos
);
155 grouped_draw_items
.GetAt(rect_id
).clip_rect
= item
;
156 POSITION pos_item
= item
.item_ex_list
->GetHeadPosition();
159 CompositeDrawItemEx
* draw_item_ex
= item
.item_ex_list
->GetNext(pos_item
);
160 if( draw_item_ex
->rect_id_list
.GetTail() != rect_id
)//wipe out repeated item. this safe since the list has a dummy item -1
161 draw_item_ex
->rect_id_list
.AddTail(rect_id
);
164 for (int i
=0;i
<draw_item_ex_tree
.GetCount();i
++)
166 CompositeDrawItemExVec
&draw_item_ex_vec
= draw_item_ex_tree
[i
];
167 for (int j
=0;j
<draw_item_ex_vec
.GetCount();j
++)
169 CompositeDrawItemEx
&draw_item_ex
= draw_item_ex_vec
[j
];
170 if (draw_item_ex
.item
->shadow
)
172 pos
= draw_item_ex
.rect_id_list
.GetHeadPosition();;
173 draw_item_ex
.rect_id_list
.GetNext(pos
);
176 int id
= draw_item_ex
.rect_id_list
.GetNext(pos
);
177 grouped_draw_items
[id
].draw_item_list
.AddTail( draw_item_ex
.item
->shadow
);
181 for (int j
=0;j
<draw_item_ex_vec
.GetCount();j
++)
183 CompositeDrawItemEx
&draw_item_ex
= draw_item_ex_vec
[j
];
184 if (draw_item_ex
.item
->outline
)
186 pos
= draw_item_ex
.rect_id_list
.GetHeadPosition();;
187 draw_item_ex
.rect_id_list
.GetNext(pos
);
190 int id
= draw_item_ex
.rect_id_list
.GetNext(pos
);
191 grouped_draw_items
[id
].draw_item_list
.AddTail( draw_item_ex
.item
->outline
);
195 for (int j
=0;j
<draw_item_ex_vec
.GetCount();j
++)
197 CompositeDrawItemEx
&draw_item_ex
= draw_item_ex_vec
[j
];
198 if (draw_item_ex
.item
->body
)
200 pos
= draw_item_ex
.rect_id_list
.GetHeadPosition();;
201 draw_item_ex
.rect_id_list
.GetNext(pos
);
204 int id
= draw_item_ex
.rect_id_list
.GetNext(pos
);
205 grouped_draw_items
[id
].draw_item_list
.AddTail( draw_item_ex
.item
->body
);
211 for (int i
=0;i
<grouped_draw_items
.GetCount();i
++)
213 GroupedDrawItems
& item
= grouped_draw_items
[i
];
214 pos
= item
.draw_item_list
.GetHeadPosition();
217 DrawItem::Draw(spd
, *item
.draw_item_list
.GetNext(pos
), item
.clip_rect
);
222 void CreateDrawItemExTree( CompositeDrawItemListList
& input
,
223 CompositeDrawItemExTree
*out_draw_item_ex_tree
,
224 XyRectExList
*out_rect_ex_list
)
226 ASSERT(out_draw_item_ex_tree
!=NULL
&& out_rect_ex_list
!=NULL
);
228 int list_count
= input
.GetCount();
229 out_draw_item_ex_tree
->SetCount(list_count
);
230 POSITION list_pos
= input
.GetHeadPosition();
231 for (int list_id
=0;list_id
<list_count
;list_id
++)
233 CompositeDrawItemList
& compDrawItemList
= input
.GetNext(list_pos
);
234 int count
= compDrawItemList
.GetCount();
235 CompositeDrawItemExVec
& out_draw_item_exs
= out_draw_item_ex_tree
->GetAt(list_id
);
236 out_draw_item_exs
.SetCount(count
);
237 POSITION item_pos
= compDrawItemList
.GetHeadPosition();
238 for (int item_id
=0; item_id
<count
; item_id
++ )
240 CompositeDrawItem
& comp_draw_item
= compDrawItemList
.GetNext(item_pos
);
241 CompositeDrawItemEx
& comp_draw_item_ex
= out_draw_item_exs
.GetAt(item_id
);
242 comp_draw_item_ex
.item
= &comp_draw_item
;
243 comp_draw_item_ex
.rect_id_list
.AddHead(-1);//dummy head
245 XyRectEx
&rect_ex
= out_rect_ex_list
->GetAt(out_rect_ex_list
->AddTail());
246 rect_ex
.item_ex_list
.reset(new PCompositeDrawItemExList());
247 rect_ex
.item_ex_list
->AddTail( &comp_draw_item_ex
);
248 rect_ex
.SetRect( CompositeDrawItem::GetDirtyRect(comp_draw_item
) );
253 void MergeRects(const XyRectExList
& input
, XyRectExList
* output
)
255 int input_count
= input
.GetCount();
256 if(output
==NULL
|| input_count
==0)
259 typedef CAtlList
<XyRectEx
> Segment
;
264 const XyRectEx
* rect
;
266 inline bool operator<(const BreakPoint
& breakpoint
) const
268 return (x
< breakpoint
.x
);
272 std::vector
<int> vertical_breakpoints(2*input_count
);
273 std::vector
<BreakPoint
> herizon_breakpoints(input_count
);
275 POSITION pos
= input
.GetHeadPosition();
276 for(int i
=0; i
<input_count
; i
++)
278 const XyRectEx
& rect
= input
.GetNext(pos
);
279 vertical_breakpoints
[2*i
]=rect
.top
;
280 vertical_breakpoints
[2*i
+1]=rect
.bottom
;
282 herizon_breakpoints
[i
].x
= rect
.left
;
283 herizon_breakpoints
[i
].rect
= &rect
;
286 std::sort(vertical_breakpoints
.begin(), vertical_breakpoints
.end());
287 std::sort(herizon_breakpoints
.begin(), herizon_breakpoints
.end());
289 CAtlArray
<Segment
> tempSegments
;
290 tempSegments
.SetCount(vertical_breakpoints
.size()-1);
291 int prev
= vertical_breakpoints
[0], count
= 0;
292 for(int ptr
= 1; ptr
<vertical_breakpoints
.size(); ptr
++)
294 if(vertical_breakpoints
[ptr
] != prev
)
296 Segment
& seg
= tempSegments
[count
];
298 seg
.GetTail().SetRect(INT_MIN
, prev
, INT_MIN
, vertical_breakpoints
[ptr
]);
299 seg
.GetTail().item_ex_list
.reset(new PCompositeDrawItemExList());
301 prev
= vertical_breakpoints
[ptr
];
306 for(int i
=0; i
<input_count
; i
++)
308 const XyRectEx
& rect
= *herizon_breakpoints
[i
].rect
;
310 int start
= 0, mid
, end
= count
;
314 mid
= (start
+end
)>>1;
315 if(tempSegments
[mid
].GetTail().top
< rect
.top
)
324 for(; start
< count
; start
++)
326 CAtlList
<XyRectEx
>& cur_line
= tempSegments
[start
];
327 XyRectEx
& item
= cur_line
.GetTail();
328 if (item
.top
>= rect
.bottom
)
332 if (item
.right
<rect
.left
)
335 XyRectEx
& new_item
= cur_line
.GetTail();
336 new_item
.SetRect( rect
.left
, item
.top
, rect
.right
, item
.bottom
);
337 new_item
.item_ex_list
.reset(new PCompositeDrawItemExList());
338 new_item
.item_ex_list
->AddTailList( rect
.item_ex_list
.get() );
342 if (item
.right
<rect
.right
)
344 item
.right
= rect
.right
;
346 item
.item_ex_list
->AddTailList( rect
.item_ex_list
.get() );
351 for (int i
=count
-1;i
>0;i
--)
353 CAtlList
<XyRectEx
>& cur_line
= tempSegments
[i
];
354 CAtlList
<XyRectEx
>& upper_line
= tempSegments
[i
-1];
356 POSITION pos_cur_line
= cur_line
.GetTailPosition();
357 XyRectEx
*cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
358 if(cur_rect
->top
== upper_line
.GetTail().bottom
)
360 POSITION pos
= upper_line
.GetTailPosition();
363 XyRectEx
& upper_rect
= upper_line
.GetPrev(pos
);
364 while( upper_rect
.right
<cur_rect
->right
|| upper_rect
.left
<cur_rect
->left
)
366 output
->AddHead(*cur_rect
);
367 //if(!cur_line.IsEmpty())
368 cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
373 if(upper_rect
.right
==cur_rect
->right
&& upper_rect
.left
==cur_rect
->left
)
375 upper_rect
.bottom
= cur_rect
->bottom
;
376 upper_rect
.item_ex_list
->AddTailList( cur_rect
->item_ex_list
.get() );
377 //if(!cur_line.IsEmpty())
378 cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
380 //else if ( upper_rect.right>cur_rect.right || upper_rect.left>cur_rect.left )
385 output
->AddHead(*cur_rect
);
386 cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
391 CAtlList
<XyRectEx
>& cur_line
= tempSegments
[0];
392 POSITION pos_cur_line
= cur_line
.GetTailPosition();
393 XyRectEx
*cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
396 output
->AddHead(*cur_rect
);
397 cur_rect
= &cur_line
.GetPrev(pos_cur_line
);