5 #include <boost/shared_ptr.hpp>
6 #include "xy_overlay_paint_machine.h"
7 #include "xy_clipper_paint_machine.h"
8 #include "../SubPic/ISubPic.h"
13 //////////////////////////////////////////////////////////////////////////
17 CRect
DrawItem::GetDirtyRect()
20 if(!switchpts
|| !fBody
&& !fBorder
) return(r
);
22 ASSERT(overlay_paint_machine
);
23 CRect overlay_rect
= overlay_paint_machine
->CalcDirtyRect();
25 // Remember that all subtitle coordinates are specified in 1/8 pixels
26 // (x+4)>>3 rounds to nearest whole pixel.
27 // ??? What is xsub, ysub, mOffsetX and mOffsetY ?
28 int x
= (xsub
+ overlay_rect
.left
+ 4)>>3;
29 int y
= (ysub
+ overlay_rect
.top
+ 4)>>3;
30 int w
= overlay_rect
.Width()>>3;
31 int h
= overlay_rect
.Height()>>3;
32 r
= clip_rect
& CRect(x
, y
, x
+w
, y
+h
);
33 r
&= clipper
->CalcDirtyRect();
35 //expand the rect, so that it is possible to perform chroma sub-sampling
37 r
.right
= (r
.right
+ 1)&~1;
39 r
.bottom
= (r
.bottom
+ 1)&~1;
43 CRect
DrawItem::Draw( XyBitmap
* bitmap
, DrawItem
& draw_item
, const CRect
& clip_rect
)
46 SharedPtrGrayImage2 alpha_mask
;
47 draw_item
.clipper
->Paint(&alpha_mask
);
49 SharedPtrOverlay overlay
;
50 ASSERT(draw_item
.overlay_paint_machine
);
51 draw_item
.overlay_paint_machine
->Paint(&overlay
);
53 const SharedPtrByte
& alpha
= Rasterizer::CompositeAlphaMask(overlay
, draw_item
.clip_rect
& clip_rect
, alpha_mask
.get(),
54 draw_item
.xsub
, draw_item
.ysub
, draw_item
.switchpts
, draw_item
.fBody
, draw_item
.fBorder
,
57 Rasterizer::Draw(bitmap
, overlay
, result
, alpha
.get(),
58 draw_item
.xsub
, draw_item
.ysub
, draw_item
.switchpts
, draw_item
.fBody
, draw_item
.fBorder
);
62 DrawItem
* DrawItem::CreateDrawItem( const SharedPtrOverlayPaintMachine
& overlay_paint_machine
, const CRect
& clipRect
,
63 const SharedPtrCClipperPaintMachine
&clipper
, int xsub
, int ysub
, const DWORD
* switchpts
, bool fBody
, bool fBorder
)
65 DrawItem
* result
= new DrawItem();
66 result
->overlay_paint_machine
= overlay_paint_machine
;
67 result
->clip_rect
= clipRect
;
68 result
->clipper
= clipper
;
72 memcpy(result
->switchpts
, switchpts
, sizeof(result
->switchpts
));
73 result
->fBody
= fBody
;
74 result
->fBorder
= fBorder
;
76 result
->m_key
.reset( new DrawItemHashKey(*result
) );
77 result
->m_key
->UpdateHashValue();
82 const SharedPtrDrawItemHashKey
& DrawItem::GetHashKey()
87 //////////////////////////////////////////////////////////////////////////
92 CRect
CompositeDrawItem::GetDirtyRect( CompositeDrawItem
& item
)
97 result
|= item
.shadow
->GetDirtyRect();
101 result
|= item
.outline
->GetDirtyRect();
105 result
|= *item
.body
->GetDirtyRect();
110 //temporary data struct for the complex dirty rect splitting and draw item grouping algorithm
111 struct CompositeDrawItemEx
113 CompositeDrawItem
*item
;
114 CAtlList
<int> rect_id_list
;
118 typedef CAtlList
<CompositeDrawItemEx
*> PCompositeDrawItemExList
;
119 typedef CAtlArray
<CompositeDrawItemEx
> CompositeDrawItemExVec
;
120 typedef CAtlArray
<CompositeDrawItemExVec
> CompositeDrawItemExTree
;
122 typedef ::boost::shared_ptr
<PCompositeDrawItemExList
> SharedPCompositeDrawItemExList
;
124 class XyRectEx
: public CRect
127 SharedPCompositeDrawItemExList item_ex_list
;
129 void SetRect(const RECT
& rect
)
131 __super::operator=(rect
);
139 __super::SetRect(x1
,y1
,x2
,y2
);
143 typedef CAtlList
<XyRectEx
> XyRectExList
;
145 void MergeRects(const XyRectExList
& input
, XyRectExList
* output
);
146 void CreateDrawItemExTree( CompositeDrawItemListList
& input
,
147 CompositeDrawItemExTree
*out_draw_item_ex_tree
,
148 XyRectExList
*out_rect_ex_list
);
150 void CompositeDrawItem::Draw( XySubRenderFrame
**output
, CompositeDrawItemListList
& compDrawItemListList
)
158 CompositeDrawItemExTree draw_item_ex_tree
;
159 XyRectExList rect_ex_list
;
160 CreateDrawItemExTree(compDrawItemListList
, &draw_item_ex_tree
, &rect_ex_list
);
162 XyRectExList grouped_rect_exs
;
163 MergeRects(rect_ex_list
, &grouped_rect_exs
);
165 CAtlArray
<GroupedDrawItems
> grouped_draw_items
;
167 grouped_draw_items
.SetCount(grouped_rect_exs
.GetCount());
169 POSITION pos
= grouped_rect_exs
.GetHeadPosition();
170 for(int rect_id
=0;pos
;rect_id
++)
172 XyRectEx
& item
= grouped_rect_exs
.GetNext(pos
);
173 grouped_draw_items
.GetAt(rect_id
).clip_rect
= item
;
174 POSITION pos_item
= item
.item_ex_list
->GetHeadPosition();
177 CompositeDrawItemEx
* draw_item_ex
= item
.item_ex_list
->GetNext(pos_item
);
178 if( draw_item_ex
->rect_id_list
.GetTail() != rect_id
)//wipe out repeated item. this safe since the list has a dummy item -1
179 draw_item_ex
->rect_id_list
.AddTail(rect_id
);
182 for (unsigned i
=0;i
<draw_item_ex_tree
.GetCount();i
++)
184 CompositeDrawItemExVec
&draw_item_ex_vec
= draw_item_ex_tree
[i
];
185 for (unsigned j
=0;j
<draw_item_ex_vec
.GetCount();j
++)
187 CompositeDrawItemEx
&draw_item_ex
= draw_item_ex_vec
[j
];
188 if (draw_item_ex
.item
->shadow
)
190 pos
= draw_item_ex
.rect_id_list
.GetHeadPosition();;
191 draw_item_ex
.rect_id_list
.GetNext(pos
);
194 int id
= draw_item_ex
.rect_id_list
.GetNext(pos
);
195 grouped_draw_items
[id
].draw_item_list
.AddTail( draw_item_ex
.item
->shadow
);
199 for (unsigned j
=0;j
<draw_item_ex_vec
.GetCount();j
++)
201 CompositeDrawItemEx
&draw_item_ex
= draw_item_ex_vec
[j
];
202 if (draw_item_ex
.item
->outline
)
204 pos
= draw_item_ex
.rect_id_list
.GetHeadPosition();;
205 draw_item_ex
.rect_id_list
.GetNext(pos
);
208 int id
= draw_item_ex
.rect_id_list
.GetNext(pos
);
209 grouped_draw_items
[id
].draw_item_list
.AddTail( draw_item_ex
.item
->outline
);
213 for (unsigned j
=0;j
<draw_item_ex_vec
.GetCount();j
++)
215 CompositeDrawItemEx
&draw_item_ex
= draw_item_ex_vec
[j
];
216 if (draw_item_ex
.item
->body
)
218 pos
= draw_item_ex
.rect_id_list
.GetHeadPosition();;
219 draw_item_ex
.rect_id_list
.GetNext(pos
);
222 int id
= draw_item_ex
.rect_id_list
.GetNext(pos
);
223 grouped_draw_items
[id
].draw_item_list
.AddTail( draw_item_ex
.item
->body
);
229 XySubRenderFrameCreater
*render_frame_creater
= XySubRenderFrameCreater::GetDefaultCreater();
231 *output
= render_frame_creater
->NewXySubRenderFrame(grouped_draw_items
.GetCount());
232 XySubRenderFrame
& sub_render_frame
= **output
;
234 for (unsigned i
=0;i
<grouped_draw_items
.GetCount();i
++)
236 grouped_draw_items
[i
].Draw(&(sub_render_frame
.m_bitmaps
.GetAt(i
)), &(sub_render_frame
.m_bitmap_ids
.GetAt(i
)));
240 void CreateDrawItemExTree( CompositeDrawItemListList
& input
,
241 CompositeDrawItemExTree
*out_draw_item_ex_tree
,
242 XyRectExList
*out_rect_ex_list
)
244 ASSERT(out_draw_item_ex_tree
!=NULL
&& out_rect_ex_list
!=NULL
);
246 int list_count
= input
.GetCount();
247 out_draw_item_ex_tree
->SetCount(list_count
);
248 POSITION list_pos
= input
.GetHeadPosition();
249 for (int list_id
=0;list_id
<list_count
;list_id
++)
251 CompositeDrawItemList
& compDrawItemList
= input
.GetNext(list_pos
);
252 int count
= compDrawItemList
.GetCount();
253 CompositeDrawItemExVec
& out_draw_item_exs
= out_draw_item_ex_tree
->GetAt(list_id
);
254 out_draw_item_exs
.SetCount(count
);
255 POSITION item_pos
= compDrawItemList
.GetHeadPosition();
256 for (int item_id
=0; item_id
<count
; item_id
++ )
258 CompositeDrawItem
& comp_draw_item
= compDrawItemList
.GetNext(item_pos
);
259 CompositeDrawItemEx
& comp_draw_item_ex
= out_draw_item_exs
.GetAt(item_id
);
260 comp_draw_item_ex
.item
= &comp_draw_item
;
261 comp_draw_item_ex
.rect_id_list
.AddHead(-1);//dummy head
263 XyRectEx
&rect_ex
= out_rect_ex_list
->GetAt(out_rect_ex_list
->AddTail());
264 rect_ex
.item_ex_list
.reset(new PCompositeDrawItemExList());
265 rect_ex
.item_ex_list
->AddTail( &comp_draw_item_ex
);
266 rect_ex
.SetRect( CompositeDrawItem::GetDirtyRect(comp_draw_item
) );
271 void MergeRects(const XyRectExList
& input
, XyRectExList
* output
)
273 int input_count
= input
.GetCount();
274 if(output
==NULL
|| input_count
==0)
277 typedef CAtlList
<XyRectEx
> Segment
;
282 const XyRectEx
* rect
;
284 inline bool operator<(const BreakPoint
& breakpoint
) const
286 return (x
< breakpoint
.x
);
290 std::vector
<int> vertical_breakpoints(2*input_count
);
291 std::vector
<BreakPoint
> herizon_breakpoints(input_count
);
293 POSITION pos
= input
.GetHeadPosition();
294 for(int i
=0; i
<input_count
; i
++)
296 const XyRectEx
& rect
= input
.GetNext(pos
);
297 vertical_breakpoints
[2*i
]=rect
.top
;
298 vertical_breakpoints
[2*i
+1]=rect
.bottom
;
300 herizon_breakpoints
[i
].x
= rect
.left
;
301 herizon_breakpoints
[i
].rect
= &rect
;
304 std::sort(vertical_breakpoints
.begin(), vertical_breakpoints
.end());
305 std::sort(herizon_breakpoints
.begin(), herizon_breakpoints
.end());
307 CAtlArray
<Segment
> tempSegments
;
308 tempSegments
.SetCount(vertical_breakpoints
.size()-1);
309 int prev
= vertical_breakpoints
[0], count
= 0;
310 for(unsigned ptr
= 1; ptr
<vertical_breakpoints
.size(); ptr
++)
312 if(vertical_breakpoints
[ptr
] != prev
)
314 Segment
& seg
= tempSegments
[count
];
316 seg
.GetTail().SetRect(INT_MIN
, prev
, INT_MIN
, vertical_breakpoints
[ptr
]);
317 seg
.GetTail().item_ex_list
.reset(new PCompositeDrawItemExList());
319 prev
= vertical_breakpoints
[ptr
];
324 for(int i
=0; i
<input_count
; i
++)
326 const XyRectEx
& rect
= *herizon_breakpoints
[i
].rect
;
328 int start
= 0, mid
, end
= count
;
332 mid
= (start
+end
)>>1;
333 if(tempSegments
[mid
].GetTail().top
< rect
.top
)
342 for(; start
< count
; start
++)
344 CAtlList
<XyRectEx
>& cur_line
= tempSegments
[start
];
345 XyRectEx
& item
= cur_line
.GetTail();
346 if (item
.top
>= rect
.bottom
)
350 if (item
.right
<rect
.left
)
353 XyRectEx
& new_item
= cur_line
.GetTail();
354 new_item
.SetRect( rect
.left
, item
.top
, rect
.right
, item
.bottom
);
355 new_item
.item_ex_list
.reset(new PCompositeDrawItemExList());
356 new_item
.item_ex_list
->AddTailList( rect
.item_ex_list
.get() );
360 if (item
.right
<rect
.right
)
362 item
.right
= rect
.right
;
364 item
.item_ex_list
->AddTailList( rect
.item_ex_list
.get() );
369 for (int i
=count
-1;i
>0;i
--)
371 CAtlList
<XyRectEx
>& cur_line
= tempSegments
[i
];
372 CAtlList
<XyRectEx
>& upper_line
= tempSegments
[i
-1];
374 POSITION pos_cur_line
= cur_line
.GetTailPosition();
375 XyRectEx
*cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
376 if(cur_rect
->top
== upper_line
.GetTail().bottom
)
378 POSITION pos
= upper_line
.GetTailPosition();
381 XyRectEx
& upper_rect
= upper_line
.GetPrev(pos
);
382 while( upper_rect
.right
<cur_rect
->right
|| upper_rect
.left
<cur_rect
->left
)
384 output
->AddHead(*cur_rect
);
385 //if(!cur_line.IsEmpty())
386 cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
391 if(upper_rect
.right
==cur_rect
->right
&& upper_rect
.left
==cur_rect
->left
)
393 upper_rect
.bottom
= cur_rect
->bottom
;
394 upper_rect
.item_ex_list
->AddTailList( cur_rect
->item_ex_list
.get() );
395 //if(!cur_line.IsEmpty())
396 cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
398 //else if ( upper_rect.right>cur_rect.right || upper_rect.left>cur_rect.left )
403 output
->AddHead(*cur_rect
);
404 cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
409 CAtlList
<XyRectEx
>& cur_line
= tempSegments
[0];
410 POSITION pos_cur_line
= cur_line
.GetTailPosition();
411 XyRectEx
*cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
414 output
->AddHead(*cur_rect
);
415 cur_rect
= &cur_line
.GetPrev(pos_cur_line
);
420 //////////////////////////////////////////////////////////////////////////
425 void GroupedDrawItems::Draw( SharedPtrXyBitmap
*bitmap
, int *bitmap_identity_num
)
429 ASSERT(bitmap
&& bitmap_identity_num
);
430 BitmapMruCache
*bitmap_cache
= CacheManager::GetBitmapMruCache();
431 GroupedDrawItemsHashKey key
= GetHashKey();
432 POSITION pos
= bitmap_cache
->Lookup(key
);
435 POSITION pos
= draw_item_list
.GetHeadPosition();
436 XyBitmap
*tmp
= XySubRenderFrameCreater::GetDefaultCreater()->CreateBitmap(clip_rect
);
440 DrawItem::Draw(tmp
, *draw_item_list
.GetNext(pos
), clip_rect
);
442 bitmap_cache
->UpdateCache(key
, *bitmap
);
446 *bitmap
= bitmap_cache
->GetAt(pos
);
447 bitmap_cache
->UpdateCache(pos
);
449 *bitmap_identity_num
= id
++;//fix me: not really support id yet
452 GroupedDrawItemsHashKey
GroupedDrawItems::GetHashKey()
454 GroupedDrawItemsHashKey key
;
455 key
.m_clip_rect
= clip_rect
;
456 GroupedDrawItemsHashKey::Keys
*inner_key
= new GroupedDrawItemsHashKey::Keys();
458 key
.m_key
.reset(inner_key
);
459 inner_key
->SetCount(draw_item_list
.GetCount());
460 POSITION pos
= draw_item_list
.GetHeadPosition();
461 for (unsigned i
=0;i
<inner_key
->GetCount();i
++)
463 inner_key
->GetAt(i
) = draw_item_list
.GetNext(pos
)->GetHashKey();
465 key
.UpdateHashValue();