00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "usfsubtitles.h"
00024
00025 #define DeclareNameAndValue(pNode, name, val) \
00026 CComBSTR name; \
00027 pNode->get_nodeName(&name); \
00028 name.ToLower(); \
00029 CComVariant val; \
00030 pNode->get_nodeValue(&val); \
00031
00032 #define BeginEnumAttribs(pNode, pChild, name, value) \
00033 {CComPtr<IXMLDOMNamedNodeMap> pAttribs; \
00034 if(SUCCEEDED(pNode->get_attributes(&pAttribs)) && pAttribs != NULL) \
00035 { \
00036 CComPtr<IXMLDOMNode> pChild; \
00037 for(pAttribs->nextNode(&pChild); pChild; pChild = NULL, pAttribs->nextNode(&pChild)) \
00038 { \
00039
00040 #define EndEnumAttribs }}}
00041
00042 #define BeginEnumChildren(pNode, pChild) \
00043 {CComPtr<IXMLDOMNode> pChild, pNext; \
00044 for(pNode->get_firstChild(&pChild); pChild; pNext = NULL, pChild->get_nextSibling(&pNext), pChild = pNext) \
00045 { \
00046
00047 #define EndEnumChildren }}
00048
00049 static CStringW GetText(CComPtr<IXMLDOMNode> pNode)
00050 {
00051 CComBSTR bstr;
00052 pNode->get_text(&bstr);
00053
00054 return(CStringW(bstr));
00055 }
00056
00057 static CStringW GetXML(CComPtr<IXMLDOMNode> pNode)
00058 {
00059 CComBSTR bstr;
00060 pNode->get_xml(&bstr);
00061 CStringW str(bstr);
00062 str.Remove('\r');
00063 str.Replace('\n', ' ');
00064 for(int i = 0; (i = str.Find(L" ", i)) >= 0; )
00065 {
00066 for(++i; i < str.GetLength() && (str[i] == '\n' || str[i] == ' ');)
00067 str.Delete(i);
00068 }
00069 return(str);
00070 }
00071
00072 static CStringW GetAttrib(CStringW attrib, CComPtr<IXMLDOMNode> pNode)
00073 {
00074 CStringW ret;
00075
00076 BeginEnumAttribs(pNode, pChild, name, val)
00077 {
00078 DeclareNameAndValue(pChild, name, val);
00079
00080 if(CStringW(name) == attrib && val.vt == VT_BSTR)
00081 {
00082 ret = val.bstrVal;
00083 break;
00084 }
00085 }
00086 EndEnumAttribs
00087
00088 return(ret);
00089 }
00090
00091 static int TimeToInt(CStringW str)
00092 {
00093 CList<CStringW> sl;
00094 int i = 0;
00095 for(CStringW token = str.Tokenize(L":.,", i); !token.IsEmpty(); token = str.Tokenize(L":.,", i))
00096 sl.AddHead(token);
00097
00098 if(sl.GetCount() > 4)
00099 return(-1);
00100
00101 int time = 0;
00102
00103 int mul[4] = {1,1000,60*1000,60*60*1000};
00104 POSITION pos = sl.GetHeadPosition();
00105 for(i = 0; pos; i++)
00106 {
00107 const WCHAR* s = sl.GetNext(pos);
00108 WCHAR* tmp = NULL;
00109 int t = wcstol(s, &tmp, 10);
00110 if(s >= tmp) return(-1);
00111 time += t * mul[i];
00112 }
00113
00114 return(time);
00115 }
00116
00117 static DWORD StringToDWORD(CStringW str)
00118 {
00119 if(str.IsEmpty()) return(0);
00120 if(str[0] == '#') return((DWORD)wcstol(str, NULL, 16));
00121 else return((DWORD)wcstol(str, NULL, 10));
00122 }
00123
00124 static DWORD ColorToDWORD(CStringW str)
00125 {
00126 if(str.IsEmpty()) return(0);
00127
00128 DWORD ret = 0;
00129
00130 if(str[0] == '#')
00131 {
00132 ret = (DWORD)wcstol(str.TrimLeft('#'), NULL, 16);
00133 }
00134 else
00135 {
00136 void* color = NULL;
00137 g_colors.Lookup(CString(str), color);
00138 ret = (DWORD)color;
00139 }
00140
00141 ret = ((ret&0xff)<<16)|(ret&0xff00ff00)|((ret>>16)&0xff);
00142
00143 return(ret);
00144 }
00145
00146 static int TranslateAlignment(CStringW alignment)
00147 {
00148 return
00149 !alignment.CompareNoCase(L"BottomLeft") ? 1 :
00150 !alignment.CompareNoCase(L"BottomCenter") ? 2 :
00151 !alignment.CompareNoCase(L"BottomRight") ? 3 :
00152 !alignment.CompareNoCase(L"MiddleLeft") ? 4 :
00153 !alignment.CompareNoCase(L"MiddleCenter") ? 5 :
00154 !alignment.CompareNoCase(L"MiddleRight") ? 6 :
00155 !alignment.CompareNoCase(L"TopLeft") ? 7 :
00156 !alignment.CompareNoCase(L"TopCenter") ? 8 :
00157 !alignment.CompareNoCase(L"TopRight") ? 9 :
00158 2;
00159 }
00160
00161 static int TranslateMargin(CStringW margin, int wndsize)
00162 {
00163 int ret = 0;
00164
00165 if(!margin.IsEmpty())
00166 {
00167 ret = wcstol(margin, NULL, 10);
00168 if(margin.Find('%') >= 0) ret = wndsize * ret / 100;
00169 }
00170
00171 return(ret);
00172 }
00173
00175
00176 CUSFSubtitles::CUSFSubtitles()
00177 {
00178 }
00179
00180 CUSFSubtitles::~CUSFSubtitles()
00181 {
00182 }
00183
00184 bool CUSFSubtitles::Read(LPCTSTR fn)
00185 {
00186 VARIANT_BOOL vb;
00187 CComPtr<IXMLDOMDocument> pDoc;
00188 if(FAILED(pDoc.CoCreateInstance(CLSID_DOMDocument))
00189 || FAILED(pDoc->put_async(VARIANT_FALSE))
00190 || FAILED(pDoc->load(CComVariant(fn), &vb)) || vb != VARIANT_TRUE)
00191 return(false);
00192
00193 styles.RemoveAll();
00194 effects.RemoveAll();
00195 texts.RemoveAll();
00196
00197 if(!ParseUSFSubtitles(CComQIPtr<IXMLDOMNode>(pDoc)))
00198 return(false);
00199
00200 POSITION pos = styles.GetHeadPosition();
00201 while(pos)
00202 {
00203 style_t* def = styles.GetNext(pos);
00204
00205 if(def->name.CompareNoCase(L"Default"))
00206 continue;
00207
00208 POSITION pos2 = styles.GetHeadPosition();
00209 while(pos2)
00210 {
00211 style_t* s = styles.GetNext(pos2);
00212
00213 if(!s->name.CompareNoCase(L"Default"))
00214 continue;
00215
00216 if(s->fontstyle.face.IsEmpty()) s->fontstyle.face = def->fontstyle.face;
00217 if(s->fontstyle.size.IsEmpty()) s->fontstyle.size = def->fontstyle.size;
00218 if(s->fontstyle.color[0].IsEmpty()) s->fontstyle.color[0] = def->fontstyle.color[0];
00219 if(s->fontstyle.color[1].IsEmpty()) s->fontstyle.color[1] = def->fontstyle.color[1];
00220 if(s->fontstyle.color[2].IsEmpty()) s->fontstyle.color[2] = def->fontstyle.color[2];
00221 if(s->fontstyle.color[3].IsEmpty()) s->fontstyle.color[3] = def->fontstyle.color[3];
00222 if(s->fontstyle.italic.IsEmpty()) s->fontstyle.italic = def->fontstyle.italic;
00223 if(s->fontstyle.weight.IsEmpty()) s->fontstyle.weight = def->fontstyle.weight;
00224 if(s->fontstyle.underline.IsEmpty()) s->fontstyle.underline = def->fontstyle.underline;
00225 if(s->fontstyle.alpha.IsEmpty()) s->fontstyle.alpha = def->fontstyle.alpha;
00226 if(s->fontstyle.outline.IsEmpty()) s->fontstyle.outline = def->fontstyle.outline;
00227 if(s->fontstyle.shadow.IsEmpty()) s->fontstyle.shadow = def->fontstyle.shadow;
00228 if(s->fontstyle.wrap.IsEmpty()) s->fontstyle.wrap = def->fontstyle.wrap;
00229 if(s->pal.alignment.IsEmpty()) s->pal.alignment = def->pal.alignment;
00230 if(s->pal.relativeto.IsEmpty()) s->pal.relativeto = def->pal.relativeto;
00231 if(s->pal.horizontal_margin.IsEmpty()) s->pal.horizontal_margin = def->pal.horizontal_margin;
00232 if(s->pal.vertical_margin.IsEmpty()) s->pal.vertical_margin = def->pal.vertical_margin;
00233 if(s->pal.rotate[0].IsEmpty()) s->pal.rotate[0] = def->pal.rotate[0];
00234 if(s->pal.rotate[1].IsEmpty()) s->pal.rotate[1] = def->pal.rotate[1];
00235 if(s->pal.rotate[2].IsEmpty()) s->pal.rotate[2] = def->pal.rotate[2];
00236 }
00237
00238 break;
00239 }
00240
00241 pos = texts.GetHeadPosition();
00242 while(pos)
00243 {
00244 text_t* t = texts.GetNext(pos);
00245 if(t->style.IsEmpty()) t->style = L"Default";
00246 }
00247
00248 return(true);
00249 }
00250
00251 bool CUSFSubtitles::ConvertToSTS(CSimpleTextSubtitle& sts)
00252 {
00253 sts.m_name = metadata.language.text;
00254 sts.m_encoding = CTextFile::UTF8;
00255 sts.m_dstScreenSize = CSize(640, 480);
00256 sts.m_fScaledBAS = true;
00257 sts.m_defaultWrapStyle = 1;
00258
00259
00260 int charSet = DEFAULT_CHARSET;
00261
00262 POSITION pos = styles.GetHeadPosition();
00263 while(pos)
00264 {
00265 style_t* s = styles.GetNext(pos);
00266
00267 if(!s->name.CompareNoCase(L"Default") && !s->fontstyle.wrap.IsEmpty())
00268 {
00269 sts.m_defaultWrapStyle =
00270 !s->fontstyle.wrap.CompareNoCase(L"no") ? 2 :
00271 !s->fontstyle.wrap.CompareNoCase(L"auto") ? 1 :
00272 1;
00273 }
00274
00275 STSStyle* stss = new STSStyle;
00276 if(!stss) continue;
00277
00278 if(!s->pal.horizontal_margin.IsEmpty())
00279 stss->marginRect.left = stss->marginRect.right = TranslateMargin(s->pal.horizontal_margin, sts.m_dstScreenSize.cx);
00280 if(!s->pal.vertical_margin.IsEmpty())
00281 stss->marginRect.top = stss->marginRect.bottom = TranslateMargin(s->pal.vertical_margin, sts.m_dstScreenSize.cy);
00282
00283 stss->scrAlignment = TranslateAlignment(s->pal.alignment);
00284
00285 if(!s->pal.relativeto.IsEmpty()) stss->relativeTo =
00286 !s->pal.relativeto.CompareNoCase(L"window") ? 0 :
00287 !s->pal.relativeto.CompareNoCase(L"video") ? 1 :
00288 0;
00289
00290 stss->borderStyle = 0;
00291 if(!s->fontstyle.outline.IsEmpty()) stss->outlineWidth = wcstol(s->fontstyle.outline, NULL, 10);
00292 if(!s->fontstyle.shadow.IsEmpty()) stss->shadowDepth = wcstol(s->fontstyle.shadow, NULL, 10);
00293
00294 for(int i = 0; i < 4; i++)
00295 {
00296 DWORD color = ColorToDWORD(s->fontstyle.color[i]);
00297 int alpha = (BYTE)wcstol(s->fontstyle.alpha, NULL, 10);
00298
00299 stss->colors[i] = color & 0xffffff;
00300 stss->alpha[i] = (BYTE)(color>>24);
00301
00302 stss->alpha[i] = stss->alpha[i] + (255 - stss->alpha[i]) * min(max(alpha, 0), 100) / 100;
00303 }
00304
00305 if(!s->fontstyle.face.IsEmpty()) stss->fontName = s->fontstyle.face;
00306 if(!s->fontstyle.size.IsEmpty()) stss->fontSize = wcstol(s->fontstyle.size, NULL, 10);
00307 if(!s->fontstyle.weight.IsEmpty()) stss->fontWeight =
00308 !s->fontstyle.weight.CompareNoCase(L"normal") ? FW_NORMAL :
00309 !s->fontstyle.weight.CompareNoCase(L"bold") ? FW_BOLD :
00310 !s->fontstyle.weight.CompareNoCase(L"lighter") ? FW_LIGHT :
00311 !s->fontstyle.weight.CompareNoCase(L"bolder") ? FW_SEMIBOLD :
00312 wcstol(s->fontstyle.weight, NULL, 10);
00313 if(stss->fontWeight == 0) stss->fontWeight = FW_NORMAL;
00314 if(!s->fontstyle.italic.IsEmpty()) stss->fItalic = s->fontstyle.italic.CompareNoCase(L"yes") == 0;
00315 if(!s->fontstyle.underline.IsEmpty()) stss->fUnderline = s->fontstyle.underline.CompareNoCase(L"yes") == 0;
00316 if(!s->pal.rotate[0].IsEmpty()) stss->fontAngleZ = wcstol(s->pal.rotate[0], NULL, 10);
00317 if(!s->pal.rotate[1].IsEmpty()) stss->fontAngleX = wcstol(s->pal.rotate[1], NULL, 10);
00318 if(!s->pal.rotate[2].IsEmpty()) stss->fontAngleY = wcstol(s->pal.rotate[2], NULL, 10);
00319
00320 stss->charSet = charSet;
00321
00322 sts.AddStyle(WToT(s->name), stss);
00323 }
00324
00325 pos = texts.GetHeadPosition();
00326 while(pos)
00327 {
00328 text_t* t = texts.GetNext(pos);
00329
00330 if(!t->pal.alignment.IsEmpty())
00331 {
00332 CStringW s;
00333 s.Format(L"{\\an%d}", TranslateAlignment(t->pal.alignment));
00334 t->str = s + t->str;
00335 }
00336
00337 CRect marginRect;
00338 marginRect.SetRectEmpty();
00339
00340 if(!t->pal.horizontal_margin.IsEmpty())
00341 marginRect.left = marginRect.right = TranslateMargin(t->pal.horizontal_margin, sts.m_dstScreenSize.cx);
00342 if(!t->pal.vertical_margin.IsEmpty())
00343 marginRect.top = marginRect.bottom = TranslateMargin(t->pal.vertical_margin, sts.m_dstScreenSize.cy);
00344
00345 WCHAR rtags[3][8] = {L"{\\rz%d}", L"{\\rx%d}", L"{\\ry%d}"};
00346 for(int i = 0; i < 3; i++)
00347 {
00348 if(int angle = wcstol(t->pal.rotate[i], NULL, 10))
00349 {
00350 CStringW str;
00351 str.Format(rtags[i], angle);
00352 t->str = str + t->str;
00353 }
00354 }
00355
00356 if(t->style.CompareNoCase(L"Default") != 0)
00357 {
00358 POSITION pos = styles.GetHeadPosition();
00359 while(pos)
00360 {
00361 style_t* s = styles.GetNext(pos);
00362 if(s->name == t->style && !s->fontstyle.wrap.IsEmpty())
00363 {
00364 int WrapStyle =
00365 !s->fontstyle.wrap.CompareNoCase(L"no") ? 2 :
00366 !s->fontstyle.wrap.CompareNoCase(L"auto") ? 1 :
00367 1;
00368
00369 if(WrapStyle != sts.m_defaultWrapStyle)
00370 {
00371 CStringW str;
00372 str.Format(L"{\\q%d}", WrapStyle);
00373 t->str = str + t->str;
00374 }
00375
00376 break;
00377 }
00378 }
00379 }
00380
00381
00382
00383 sts.Add(t->str, true, t->start, t->stop, WToT(t->style), _T(""), _T(""), marginRect);
00384 }
00385
00386 return(true);
00387 }
00388
00389 bool CUSFSubtitles::ParseUSFSubtitles(CComPtr<IXMLDOMNode> pNode)
00390 {
00391 DeclareNameAndValue(pNode, name, val);
00392
00393 if(name == L"usfsubtitles")
00394 {
00395
00396
00397 BeginEnumChildren(pNode, pChild)
00398 {
00399 DeclareNameAndValue(pChild, name, val);
00400
00401 if(name == L"metadata")
00402 {
00403 ParseMetadata(pChild, metadata);
00404 }
00405 }
00406 EndEnumChildren
00407
00408
00409
00410 BeginEnumChildren(pNode, pChild)
00411 {
00412 DeclareNameAndValue(pChild, name, val);
00413
00414 if(name == L"styles")
00415 {
00416 BeginEnumChildren(pChild, pGrandChild)
00417 {
00418 DeclareNameAndValue(pGrandChild, name, val);
00419
00420 if(name == L"style")
00421 {
00422 CAutoPtr<style_t> s(new style_t);
00423 if(s)
00424 {
00425 ParseStyle(pGrandChild, s);
00426 styles.AddTail(s);
00427 }
00428 }
00429 }
00430 EndEnumChildren
00431 }
00432 }
00433 EndEnumChildren
00434
00435
00436
00437 BeginEnumChildren(pNode, pChild)
00438 {
00439 DeclareNameAndValue(pChild, name, val);
00440
00441 if(name == L"effects")
00442 {
00443 BeginEnumChildren(pChild, pGrandChild)
00444 {
00445 DeclareNameAndValue(pGrandChild, name, val);
00446
00447 if(name == L"effect")
00448 {
00449 CAutoPtr<effect_t> e(new effect_t);
00450 if(e)
00451 {
00452 ParseEffect(pGrandChild, e);
00453 effects.AddTail(e);
00454 }
00455 }
00456 }
00457 EndEnumChildren
00458 }
00459 }
00460 EndEnumChildren
00461
00462
00463
00464 BeginEnumChildren(pNode, pChild)
00465 {
00466 DeclareNameAndValue(pChild, name, val);
00467
00468 if(name == L"subtitles")
00469 {
00470 BeginEnumChildren(pChild, pGrandChild)
00471 {
00472 DeclareNameAndValue(pGrandChild, name, val);
00473
00474 if(name == L"subtitle")
00475 {
00476 CStringW sstart = GetAttrib(L"start", pGrandChild);
00477 CStringW sstop = GetAttrib(L"stop", pGrandChild);
00478 CStringW sduration = GetAttrib(L"duration", pGrandChild);
00479 if(sstart.IsEmpty() || (sstop.IsEmpty() && sduration.IsEmpty()))
00480 continue;
00481
00482 int start = TimeToInt(sstart);
00483 int stop = !sstop.IsEmpty() ? TimeToInt(sstop) : (start + TimeToInt(sduration));
00484
00485 ParseSubtitle(pGrandChild, start, stop);
00486 }
00487 }
00488 EndEnumChildren
00489 }
00490 }
00491 EndEnumChildren
00492
00493 return(true);
00494 }
00495
00496 BeginEnumChildren(pNode, pChild)
00497 {
00498 if(ParseUSFSubtitles(pChild))
00499 {
00500 return(true);
00501 }
00502 }
00503 EndEnumChildren
00504
00505 return(false);
00506 }
00507
00508 void CUSFSubtitles::ParseMetadata(CComPtr<IXMLDOMNode> pNode, metadata_t& m)
00509 {
00510 DeclareNameAndValue(pNode, name, val);
00511
00512 if(name == L"title")
00513 {
00514 m.title = GetText(pNode);
00515 }
00516 else if(name == L"date")
00517 {
00518 m.date = GetText(pNode);
00519 }
00520 else if(name == L"comment")
00521 {
00522 m.comment = GetText(pNode);
00523 }
00524 else if(name == L"author")
00525 {
00526 BeginEnumChildren(pNode, pChild)
00527 {
00528 DeclareNameAndValue(pChild, name, val);
00529
00530 if(name == L"name")
00531 m.author.name = GetText(pChild);
00532 else if(name == L"email")
00533 m.author.email = GetText(pChild);
00534 else if(name == L"url")
00535 m.author.url = GetText(pChild);
00536 }
00537 EndEnumChildren
00538
00539 return;
00540 }
00541 else if(name == L"language")
00542 {
00543 m.language.text = GetText(pNode);
00544 m.language.code = GetAttrib(L"code", pNode);
00545 }
00546 else if(name == L"languageext")
00547 {
00548 m.languageext.text = GetText(pNode);
00549 m.languageext.code = GetAttrib(L"code", pNode);
00550 }
00551
00552 BeginEnumChildren(pNode, pChild)
00553 {
00554 ParseMetadata(pChild, metadata);
00555 }
00556 EndEnumChildren
00557 }
00558
00559 void CUSFSubtitles::ParseStyle(CComPtr<IXMLDOMNode> pNode, style_t* s)
00560 {
00561 DeclareNameAndValue(pNode, name, val);
00562
00563 if(name == L"style")
00564 {
00565 s->name = GetAttrib(L"name", pNode);
00566 }
00567 else if(name == L"fontstyle")
00568 {
00569 ParseFontstyle(pNode, s->fontstyle);
00570 return;
00571 }
00572 else if(name == L"position")
00573 {
00574 ParsePal(pNode, s->pal);
00575 return;
00576 }
00577
00578 BeginEnumChildren(pNode, pChild)
00579 {
00580 ParseStyle(pChild, s);
00581 }
00582 EndEnumChildren
00583 }
00584
00585 void CUSFSubtitles::ParseFontstyle(CComPtr<IXMLDOMNode> pNode, fontstyle_t& fs)
00586 {
00587 fs.face = GetAttrib(L"face", pNode);
00588 fs.size = GetAttrib(L"size", pNode);
00589 fs.color[0] = GetAttrib(L"color", pNode);
00590 fs.color[1] = GetAttrib(L"back-color", pNode);
00591 fs.color[2] = GetAttrib(L"outline-color", pNode);
00592 fs.color[3] = GetAttrib(L"shadow-color", pNode);
00593 fs.italic = GetAttrib(L"italic", pNode);
00594 fs.weight = GetAttrib(L"weight", pNode);
00595 fs.underline = GetAttrib(L"underline", pNode);
00596 fs.alpha = GetAttrib(L"alpha", pNode);
00597 fs.outline = GetAttrib(L"outline-level", pNode);
00598 fs.shadow = GetAttrib(L"shadow-level", pNode);
00599 fs.wrap = GetAttrib(L"wrap", pNode);
00600 }
00601
00602 void CUSFSubtitles::ParsePal(CComPtr<IXMLDOMNode> pNode, posattriblist_t& pal)
00603 {
00604 pal.alignment = GetAttrib(L"alignment", pNode);
00605 pal.relativeto = GetAttrib(L"relative-to", pNode);
00606 pal.horizontal_margin = GetAttrib(L"horizontal-margin", pNode);
00607 pal.vertical_margin = GetAttrib(L"vertical-margin", pNode);
00608 pal.rotate[0] = GetAttrib(L"rotate-z", pNode);
00609 pal.rotate[1] = GetAttrib(L"rotate-x", pNode);
00610 pal.rotate[2] = GetAttrib(L"rotate-y", pNode);
00611 }
00612
00613 void CUSFSubtitles::ParseEffect(CComPtr<IXMLDOMNode> pNode, effect_t* e)
00614 {
00615 DeclareNameAndValue(pNode, name, val);
00616
00617 if(name == L"effect")
00618 {
00619 e->name = GetAttrib(L"name", pNode);
00620 }
00621 else if(name == L"keyframes")
00622 {
00623 BeginEnumChildren(pNode, pChild)
00624 {
00625 DeclareNameAndValue(pChild, name, val);
00626
00627 if(name == L"keyframe")
00628 {
00629 CAutoPtr<keyframe_t> k(new keyframe_t);
00630 if(k)
00631 {
00632 ParseKeyframe(pChild, k);
00633 e->keyframes.AddTail(k);
00634 }
00635 }
00636 }
00637 EndEnumChildren
00638
00639 return;
00640 }
00641
00642 BeginEnumChildren(pNode, pChild)
00643 {
00644 ParseEffect(pChild, e);
00645 }
00646 EndEnumChildren
00647 }
00648
00649 void CUSFSubtitles::ParseKeyframe(CComPtr<IXMLDOMNode> pNode, keyframe_t* k)
00650 {
00651 DeclareNameAndValue(pNode, name, val);
00652
00653 if(name == L"keyframe")
00654 {
00655 k->position = GetAttrib(L"position", pNode);
00656 }
00657 else if(name == L"fontstyle")
00658 {
00659 ParseFontstyle(pNode, k->fontstyle);
00660 return;
00661 }
00662 else if(name == L"position")
00663 {
00664 ParsePal(pNode, k->pal);
00665 return;
00666 }
00667 }
00668
00669 void CUSFSubtitles::ParseSubtitle(CComPtr<IXMLDOMNode> pNode, int start, int stop)
00670 {
00671 DeclareNameAndValue(pNode, name, val);
00672
00673 if(name == L"text" || name == L"karaoke")
00674 {
00675 CAutoPtr<text_t> t(new text_t);
00676 if(t)
00677 {
00678 t->start = start;
00679 t->stop = stop;
00680 t->style = GetAttrib(L"style", pNode);
00681 t->effect = GetAttrib(L"effect", pNode);
00682 ParsePal(pNode, t->pal);
00683 ParseText(pNode, t->str);
00684 texts.AddTail(t);
00685 }
00686
00687 return;
00688 }
00689
00690
00691 BeginEnumChildren(pNode, pChild)
00692 {
00693 ParseSubtitle(pChild, start, stop);
00694 }
00695 EndEnumChildren
00696 }
00697
00698 void CUSFSubtitles::ParseText(CComPtr<IXMLDOMNode> pNode, CStringW& str)
00699 {
00700 DeclareNameAndValue(pNode, name, val);
00701
00702 CStringW prefix, postfix;
00703
00704 if(name == L"b")
00705 {
00706 prefix = L"{\\b1}";
00707 postfix = L"{\\b}";
00708 }
00709 else if(name == L"i")
00710 {
00711 prefix = L"{\\i1}";
00712 postfix = L"{\\i}";
00713 }
00714 else if(name == L"u")
00715 {
00716 prefix = L"{\\u1}";
00717 postfix = L"{\\u}";
00718 }
00719 else if(name == L"font")
00720 {
00721 fontstyle_t fs;
00722 ParseFontstyle(pNode, fs);
00723
00724 if(!fs.face.IsEmpty()) {prefix += L"{\\fn" + fs.face + L"}"; postfix += L"{\\fn}";}
00725 if(!fs.size.IsEmpty()) {prefix += L"{\\fs" + fs.size + L"}"; postfix += L"{\\fs}";}
00726 if(!fs.outline.IsEmpty()) {prefix += L"{\\bord" + fs.outline + L"}"; postfix += L"{\\bord}";}
00727 if(!fs.shadow.IsEmpty()) {prefix += L"{\\shad" + fs.shadow + L"}"; postfix += L"{\\shad}";}
00728
00729 for(int i = 0; i < 4; i++)
00730 {
00731 if(!fs.color[i].IsEmpty())
00732 {
00733 CStringW s;
00734 s.Format(L"{\\%dc&H%06x&}", i+1, ColorToDWORD(fs.color[i]));
00735 prefix += s;
00736 s.Format(L"{\\%dc}", i+1);
00737 postfix += s;
00738 }
00739 }
00740 }
00741 else if(name == L"k")
00742 {
00743 int t = wcstol(GetAttrib(L"t", pNode), NULL, 10);
00744 CStringW s;
00745 s.Format(L"{\\kf%d}", t / 10);
00746 str += s;
00747 return;
00748 }
00749 else if(name == L"br")
00750 {
00751 str += L"\\N";
00752 return;
00753 }
00754 else if(name == L"#text")
00755 {
00756 str += GetXML(pNode);
00757 return;
00758 }
00759
00760 BeginEnumChildren(pNode, pChild)
00761 {
00762 CStringW s;
00763 ParseText(pChild, s);
00764 str += s;
00765 }
00766 EndEnumChildren
00767
00768 str = prefix + str + postfix;
00769 }
00770
00771 void CUSFSubtitles::ParseShape(CComPtr<IXMLDOMNode> pNode)
00772 {
00773
00774 }