3gppttrenderer.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:167k
源码类别:

Symbian

开发平台:

C/C++

  1.                     INT32 iCharsToSkipOver = 0;
  2.                     INT32 iNumLinesOfTextAtStart = 0;
  3. #endif
  4.                     // /To fix it so boxes aren't drawn where newlines are,
  5.                     // skip past newlines which can only exist at the start
  6.                     // of this T.C. (fixes Helix Issue 840):
  7.                     if (HX_3GPPTT_INVALID_INT16 !=
  8.                             pTextContainer->m_lNumUTF16NewlineCharsAtStart  &&
  9.                             pTextContainer->m_lNumUTF16NewlineCharsAtStart > 0)
  10.                     {
  11.                         iCharsToSkipOver =
  12.                                 pTextContainer->m_lNumUTF16NewlineCharsAtStart;
  13.                         iNumLinesOfTextAtStart =
  14.                                 pTextContainer->m_lNumUTF16NewlinesAtStart;
  15.                         if (HX_3GPPTT_INVALID_INT16 ==
  16.                                 pTextContainer->m_lNumUTF16NewlinesAtStart)
  17.                         {
  18.                             iNumLinesOfTextAtStart = iCharsToSkipOver;
  19.                         }
  20.                         if (iCharsToSkipOver > lTextLenInChars)
  21.                         {
  22.                             HX_ASSERT(0); // /Shouldn't get here.
  23.                             // /"handle" this exception:
  24.                             iCharsToSkipOver = lTextLenInChars;
  25.                         }
  26.                         // /Reduce text len to = # chars to be rendered:
  27.                         lTextLenInChars -= (INT16)iCharsToSkipOver;
  28.                     }
  29. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  30.                     RECT RECTDrawRect;
  31.                     RECTDrawRect.left = drawRect.left;
  32.                     RECTDrawRect.top = drawRect.top;
  33.                     RECTDrawRect.right = drawRect.right;
  34.                     RECTDrawRect.bottom = drawRect.bottom;
  35.                     // /Call DrawText to get bounding rect.  (This call
  36.                     // doesn't perform a draw):
  37.                     DrawText(hDC,
  38.                             // /XXXEH- todo: handle wide chars (UTF-8, 16):
  39.                             LPSTR(pConvertedText),
  40.                             lConvertedTextLen,
  41.                             &RECTDrawRect,
  42.                             // /XXXEH- todo: finish text format (handle r-to-l):
  43.                             // DT_NOCLIP | DT_VCENTER , DT_BOTTOM , DT_TOP v-alignment |
  44.                             // DT_WORDBREAK<--NO!!We don't want auto wordwrap!! |
  45.                             // DT_CENTER/DT_RIGHT/DT_LEFT h-alignment,
  46.                             // bidi (r-to-l) (| DT_RTLREADING):
  47.                             ulTextFormatFlags | DT_CALCRECT
  48.                             // /Note; we could use DrawTextEX with a 6th parameter,
  49.                             // DRAWTEXTPARAMS, if we want to set tab stops, ...etc:
  50.                             );
  51.                     pTextContainer->m_BoundingRectOfInitialDraw.left =
  52.                             RECTDrawRect.left;
  53.                     pTextContainer->m_BoundingRectOfInitialDraw.top =
  54.                             RECTDrawRect.top;
  55.                     pTextContainer->m_BoundingRectOfInitialDraw.right =
  56.                             RECTDrawRect.right;
  57.                     pTextContainer->m_BoundingRectOfInitialDraw.bottom =
  58.                             RECTDrawRect.bottom;
  59. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  60. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  61. if (pFile)
  62. {
  63.     char* pContents = new char[lConvertedTextLen + 1];
  64.     pContents[lConvertedTextLen] = '';
  65.     strncpy(pContents, pConvertedText, lConvertedTextLen);
  66.     fprintf(pFile, "Drawing {{{%s}}} at time %lu at location: (%ld,%ld), "
  67.         "m_pTextContainerListFutureTimePos=%pn", pContents,
  68.         m_ulTimeOfLastTimeSync, drawRect.left, drawRect.top,
  69.         m_pTextContainerListFutureTimePos);
  70.     fclose(pFile);
  71.     delete [] pContents;
  72. }
  73. ulCount++;
  74. #endif  // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  75.                     // /Reset bounding rect and do actual draw w/out DT_CALCRECT:
  76.                     RECTDrawRect.left = drawRect.left;
  77.                     RECTDrawRect.top = drawRect.top;
  78.                     RECTDrawRect.right = drawRect.right;
  79.                     RECTDrawRect.bottom = drawRect.bottom;
  80. #if defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  81. #else
  82.                     RECTDrawRect.left += lXScrollOffset;
  83.                     RECTDrawRect.top += lYScrollOffset;
  84.                     if (1==ulTextContainersHandled  &&  scrollDirNone != scrolldir)
  85.                     {
  86.                         // /XXXEH- inefficient but this is a work-around until core
  87.                         // bug is fixed:
  88.                         FillRectangle(ulBgColorARGB);
  89.                     }
  90. #endif // /End else of defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  91.                     // /lTextLenInChars can be 0 if T.C.'s text is 100%
  92.                     // newline chars, so (obviously) don't draw in that case:
  93.                     if (lTextLenInChars > 0)
  94.                     {
  95.                         UINT32 ulHeightOfTextOutput =
  96.                             DrawText(hDC,
  97.                             // /XXXEH- todo: handle wide chars (UTF-8, 16):
  98.                             LPSTR(pConvertedText),
  99.                             lConvertedTextLen,
  100.                             &RECTDrawRect,
  101.                             // /XXXEH- finish text format (handle r-to-l):
  102.                             // DT_NOCLIP | DT_VCENTER , DT_BOTTOM , DT_TOP v-alignment |
  103.                             // DT_WORDBREAK<--NO!!We don't want auto wordwrap!! |
  104.                             // DT_CENTER/DT_RIGHT/DT_LEFT h-alignment,
  105.                             // bidi (r-to-l) (| DT_RTLREADING):
  106.                             ulTextFormatFlags
  107.                             );
  108.                     }
  109.                     SetBkMode(hDC, bkModeOld);
  110.                     HX_VECTOR_DELETE(pConvertedText);
  111. #elif defined(_SYMBIAN) // /                                                   ------------------------------------
  112.                 pHBufUTF16Text = HBufC16::NewMax((TInt)lTextLenInChars);
  113.                 if (lTextLenInChars <= 0  &&  pHBufUTF16Text)
  114.                 {
  115.                     // /Skip drawing this TextContainer if it was all newlines:
  116.                     delete pHBufUTF16Text;
  117.                     pHBufUTF16Text = NULL;
  118.                 }
  119.                 // /Convert it if needed, then draw it:
  120.                 {
  121.                     TInt cxText = 0;
  122.                     if (pHBufUTF16Text)
  123.                     {
  124.                         // /UTF-8 to UTF-16 translation:
  125.                         if (bTextContainerTextIsUTF16Encoded)
  126.                         {
  127.                             TInt leadByteOffset = 0;
  128.                             TInt trailingByteOffset = 1;
  129.                             if (bTextContainerTextIsUTF16ReverseEncoded)
  130.                             {
  131.                                 leadByteOffset = 1;
  132.                                 trailingByteOffset = 0;
  133.                             }
  134.                             for (TInt i = 0; i < (TInt)lTextLenInChars ; i++) 
  135.                             {
  136.                                 pHBufUTF16Text->Des()[i] =
  137.                                         ((UINT16)(pConvertedText[
  138.                                             ((i + iCharsToSkipOver) * 2) +
  139.                                             leadByteOffset])) << 8 |
  140.                                         pConvertedText[
  141.                                             ((i + iCharsToSkipOver) * 2) +
  142.                                             trailingByteOffset];
  143.                             }
  144.                         }
  145.                         else
  146.                         {
  147.                             pHBufUTF8Text = HBufC8::NewMax((TInt)
  148.                                     lTextLenInChars);
  149.                             for (TInt i = 0; i < (TInt)lTextLenInChars ; i++) 
  150.                             {
  151.                                 pHBufUTF8Text->Des()[i] = (UINT8)
  152.                                        (pConvertedText[i + iCharsToSkipOver]);
  153.                             }
  154.                             TInt kErr =
  155.                                     CnvUtfConverter::ConvertToUnicodeFromUtf8(
  156.                                     pHBufUTF16Text->Des(),
  157.                                     pHBufUTF8Text->Des() );
  158.                             delete pHBufUTF8Text;
  159.                         }
  160.                         // /Get bounding rect (width of entire UTF-16 string):
  161.                         cxText = m_pFont->TextWidthInPixels(pHBufUTF16Text->Des());
  162.                     }
  163.                     TRect RECTDrawRect(0,0,1,1);
  164.                     RECTDrawRect.iTl.iX = drawRect.left;
  165.                     RECTDrawRect.iTl.iY = drawRect.top;
  166.                     RECTDrawRect.iBr.iX = drawRect.right;
  167.                     RECTDrawRect.iBr.iY = drawRect.bottom;
  168. #pragma message("----#### these will be wrong for bottom, h,v-centered, & right-aligned ####----")
  169.                     pTextContainer->m_BoundingRectOfInitialDraw.left =
  170.                             drawRect.left;
  171.                     pTextContainer->m_BoundingRectOfInitialDraw.top =
  172.                             drawRect.top;
  173.                     pTextContainer->m_BoundingRectOfInitialDraw.right =
  174.                             drawRect.left + cxText;
  175. #pragma message("----#### this will be wrong for text containing newline chars:         ####----")
  176.                     pTextContainer->m_BoundingRectOfInitialDraw.bottom =
  177.                             drawRect.top + ulScaledHeight;
  178. #if defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  179. #else
  180.                     RECTDrawRect.iTl.iX += lXScrollOffset;
  181.                     RECTDrawRect.iTl.iY += lYScrollOffset;
  182.                     // /Make sure we don't cut off bottom right:
  183.                     RECTDrawRect.iBr.iX += lXScrollOffset;
  184.                     RECTDrawRect.iBr.iY += lYScrollOffset;
  185.                     if (1==ulTextContainersHandled  &&  scrollDirNone != scrolldir)
  186.                     {
  187.                         // /XXXEH- inefficient but this is a work-around until core
  188.                         // bug is fixed:
  189.                         FillRectangle(ulBgColorARGB);
  190.                     }
  191. #endif // /End else of defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  192.                     CGraphicsContext::TTextAlign talignHoriz = CGraphicsContext::ELeft;
  193.                     if (HX_3GPPTT_JUSTIFY_HCENTER & ulTextFormatFlags)
  194.                     {
  195.                         talignHoriz = CGraphicsContext::ECenter;
  196.                     }
  197.                     else if (HX_3GPPTT_JUSTIFY_RIGHT & ulTextFormatFlags)
  198.                     {
  199.                         talignHoriz = CGraphicsContext::ERight;
  200.                     }
  201.                     // /Top aligned (by default):
  202.                     // /Baseline is relative to RECTDrawRect passed into
  203.                     // DrawText:
  204.                     TInt tiBaseline = m_pFont->AscentInPixels();
  205.                     if (ulTextFormatFlags & HX_3GPPTT_JUSTIFY_VCENTER)
  206.                     {
  207.                         // /Vertically centered:
  208.                         tiBaseline = ( (ulScaledHeight *
  209.                                 iNumLinesOfTextAtStart) +
  210.                                 RECTDrawRect.iBr.iY - RECTDrawRect.iTl.iY +
  211.                                 m_pFont->AscentInPixels() ) / 2;
  212.                     }
  213.                     else if (ulTextFormatFlags & HX_3GPPTT_JUSTIFY_BOTTOM)
  214.                     {
  215. #pragma message("----#### need to test this with multi-line text: ####----")
  216.                         // /Justified to bottom:
  217.                         tiBaseline = RECTDrawRect.iBr.iY - ulScaledHeight +
  218.                                 m_pFont->AscentInPixels();
  219.                     }
  220.                     
  221.                     // /void DrawText(const TDesC& aText,const TPoint& aPosition); // /Draws text without a surrounding box.
  222.                     // /void DrawText(const TDesC& aText,const TRect& aBox,TInt aBaselineOffset,TTextAlign aHrz=ELeft,TInt aMargin=0);
  223.                     // /void DrawText(const TDesC& aText); // /Draws text at the last print position
  224.                     m_pGCOffscreen->SetPenStyle(CGraphicsContext::ESolidPen);
  225.                     // /lTextLenInChars can be 0 if T.C.'s text is 100%
  226.                     // newline chars, so (obviously) don't draw in that case:
  227.                     if (lTextLenInChars > 0)
  228.                     {
  229. #define XXXEH_20031126_TESTING_HIGHLIGHTCOLORING_AREA_FIX 20031126
  230. #if defined(XXXEH_20031126_TESTING_HIGHLIGHTCOLORING_AREA_FIX)
  231.                         if (bHasHighlightColor)
  232.                         {
  233.                             // /XXXEH- fixes Symbian problems where highlighted
  234.                             // background area was too big.  Further confine it to
  235.                             // top-left plus width,height of Text:
  236.                             if (talignHoriz == CGraphicsContext::ECenter  ||
  237.                                     talignHoriz == CGraphicsContext::ERight)
  238.                             {
  239.                                 // /XXXEH- todo: rewrite horizontal alignment to do it
  240.                                 // ourselves instead of letting OS do it:
  241.                                 // /Need to rework all this code so color highlighting
  242.                                 // will work.  Unfortunately we have no way of knowing
  243.                                 // where the OS places a phrase within a group of them
  244.                                 // on the same line that are drawn in different TextOut
  245.                                 // calls, so we can't know where to draw the rectangle
  246.                                 // behind it (and, unlike on Windows, the API doesn't
  247.                                 // highlight behind the text but rather behind the
  248.                                 // bounding rectangle you specify.  In order to specify
  249.                                 // that, we need to know the exact location:
  250. // /                                HX_ASSERT(0);
  251.                             }
  252.                             else
  253.                             {
  254.                                 RECTDrawRect.iBr.iX = drawRect.left + cxText + 1 +
  255.                                         // /Adjust bounding box for horiz-scrolling:
  256.                                         m_lXScrollOffset;
  257.                             }
  258.                             RECTDrawRect.iBr.iY = tiBaseline +
  259.                                     // /Adjust bounding box for vertical-scrolling:
  260.                                     m_lYScrollOffset +
  261.                                     // /Allow for descenders:
  262.                                     m_pFont->DescentInPixels();
  263.                         }
  264. #endif // /end XXXEH_20031126_TESTING_HIGHLIGHTCOLORING_AREA_FIX.
  265.                         m_pGCOffscreen->DrawText(
  266.                                 pHBufUTF16Text->Des(),
  267.                                 RECTDrawRect,
  268.                                 tiBaseline,
  269.                                 talignHoriz);
  270.                     }
  271. #if defined(_SYMBIAN)  &&  defined(_DEBUG)                                     // -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  272. //#define XXXEH_TEST_DRAWTEXT
  273. #if defined(XXXEH_TEST_DRAWTEXT)
  274. #pragma message("====##### Test code is active! Don't check it in enabled: ####----")
  275. // /If no text, draw a rect and see if it got drawn to the offscreen bitmap:
  276. {
  277.     TSize tsz(5, 5);
  278.     m_pGCOffscreen->SetPenSize(tsz);
  279.     TRgb rgbBgColor = 0x7700FF;
  280.     m_pGCOffscreen->SetBrushStyle(CGraphicsContext::ESolidBrush);
  281.     m_pGCOffscreen->SetBrushColor(rgbBgColor);
  282.     const TRect aRect(10,10,40,40);
  283.     m_pGCOffscreen->DrawRect(aRect);
  284. }
  285. #endif // /XXXEH_TEST_DRAWTEXT.
  286. #endif // /_SYMBAIN  &&  _DEBUG                                                _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  287.                     delete pHBufUTF16Text;
  288.                     if (bHasHighlightColor)
  289.                     {
  290.                         // /Undo setting of brush for bgcolor:
  291.                         m_pGCOffscreen->SetBrushStyle(CGraphicsContext::ENullBrush);
  292.                     }
  293.                 }
  294. #else  // /else of: #if defined _WINDOWS, #elif defined _SYMBIAN               ------------------------------------
  295. #pragma message("====##### This OS needs code that draws text & sets TC bounding rect #####====")
  296. #endif // /end else of: _WINDOWS                                               _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  297.                 }
  298. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  299. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  300. if (pFile)
  301. {
  302.     char* pContents = new char[lConvertedTextLen + 1];
  303.     pContents[lConvertedTextLen] = '';
  304.     strncpy(pContents, pConvertedText, lConvertedTextLen);
  305.     fprintf(pFile, "Drawing {{{%s}}} at time %lu at location: (%ld,%ld), "
  306.         "m_pTextContainerListFutureTimePos=%pn", pContents,
  307.         m_ulTimeOfLastTimeSync, drawRect.left, drawRect.top,
  308.         m_pTextContainerListFutureTimePos);
  309.     fclose(pFile);
  310.     delete [] pContents;
  311. }
  312. ulCount++;
  313. #endif  // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  314.                 liCursorX = pTextContainer->m_BoundingRectOfInitialDraw.right + 1;
  315.                 // /Note: don't update liCursorY; we'll calculate that when
  316.                 // processing the next T.C. w/its numNewlines (if any).
  317.                 pLastHandledTextSampleEntry = pCurTextSampleEntry;
  318.             }
  319.             // /If T.C. is not time-valid and it is from the main list and the
  320.             // redraw list exists, we'll next go through the redraw list:
  321.             else if (m_pTextContainerRedrawList  &&
  322.                     bTextContainerIsFromMainList  &&
  323.                     !bATextContainerFromMainListWasHandled)
  324.             {
  325.                 // /None from main list so let's look in redraw list:
  326.                 bGetTextContainersFromRedrawList = TRUE;
  327.             }
  328.             else // /We've hit future ones, so stop:
  329.             {
  330. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  331. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  332. if (pFile)
  333. {
  334.     fprintf(pFile, "[step (FinishedWthTCsAtCurTime)] T.C. = %p at time %lu ("
  335.         "text containers handled = %ld), m_pTextContainerListFutureTimePos=%pn",
  336.         pTextContainer, m_ulTimeOfLastTimeSync, ulTextContainersHandled,
  337.         m_pTextContainerListFutureTimePos);
  338.     fclose(pFile);
  339. }
  340. ulCount++;
  341. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  342.                 bFinishedWithCurTimeTCs = TRUE;
  343.             }
  344.         } while (!bFinishedWithCurTimeTCs  &&
  345.                 (m_pTextContainerListFutureTimePos  ||
  346.                 !bTextContainerIsFromMainList) );
  347.         //------------------- END TEXT PUT-GLYPHS-TO-cANVAS CODE.  ----------
  348.     } // /end: if (m_pDrawOutputBuffer  &&...
  349. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  350. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  351. if (pFile)
  352. {
  353.     fprintf(pFile, "[step (EXITED while loop)] T.C. = %p at time %lu, "
  354.         "m_pTextContainerListFutureTimePos=%pn", pTextContainer,
  355.         m_ulTimeOfLastTimeSync, m_pTextContainerListFutureTimePos);
  356.     fclose(pFile);
  357. }
  358. ulCount++;
  359. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  360.     if (m_pDrawOutputBuffer)
  361.     {
  362.         m_lXScrollOffset = lXScrollOffset;
  363.         m_lYScrollOffset = lYScrollOffset;
  364.         m_dScrollFactor = dScrollFactor;
  365.         // /First see if we have a scroll offset:
  366.         if ((lXScrollOffset  ||  lYScrollOffset)  &&  dScrollFactor > .5  &&
  367.                 pTextContainer  &&
  368.                 HX_3GPPTT_INVALID_TIME == pTextContainer->GetPrevActivityTime())
  369.         {
  370.             m_bDrawInNonTextScrollArea = TRUE;
  371.         }
  372.     }
  373.     else
  374.     {
  375.         hxrslt = HXR_UNEXPECTED;
  376.         goto cleanup;
  377.     }
  378. cleanup:
  379.     return hxrslt;
  380. }
  381. /****************************************************************************
  382.  *  C3GPPTimedTextRenderer::Draw                         ref:  3gppttrender.h
  383.  *
  384.  */
  385. HX_RESULT
  386. C3GPPTimedTextRenderer::Draw(IHXVideoSurface *pVideoSurface)
  387. {  
  388.     HX_RESULT hxrslt = HXR_OK;
  389.     SetDrawOutputBuffer();
  390.     HX_ASSERT(m_pDrawOutputBuffer);
  391.     if (m_pDrawOutputBuffer)
  392.     {
  393. #if defined(USE_DIB_SECTION) // /                                              -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  394.         HXBitmapInfoHeader* pBIHeader = (HXBitmapInfoHeader*)(&m_BITMAPINFOHEADER);
  395. #if defined(HELIX_3GPPTT_SUPPORTS_TRANSPARENCY)
  396.         pBIHeader->biCompression   = (bHasNonOpaqueAlpha ? HX_ARGB : HX_RGB);
  397. #endif // /HELIX_3GPPTT_SUPPORTS_TRANSPARENCY.
  398. #else // /_Not_ using DIB_SECTION (Dib sections are _WINDOWS-only):
  399.         HXBitmapInfoHeader* pBIHeader = &m_BitmapInfoHeader;
  400.         pBIHeader->biSize          = 40;
  401.         pBIHeader->biWidth         = m_size.cx;
  402.         pBIHeader->biHeight        = m_size.cy;
  403.         pBIHeader->biPlanes        = 1;
  404.         pBIHeader->biBitCount      = (UINT16)m_ulBitsPerPixel;
  405. #if defined(HELIX_3GPPTT_SUPPORTS_TRANSPARENCY)
  406.         pBIHeader->biCompression   = (bHasNonOpaqueAlpha ? HX_ARGB : HX_RGB);
  407. #else // /TRANSPARENCY _not_ supported:
  408.         pBIHeader->biCompression   = HX_RGB;
  409. #endif /* HELIX_3GPPTT_SUPPORTS_TRANSPARENCY */
  410.         pBIHeader->biSizeImage     = m_ulDrawOutputBufferSizeInBytes;
  411.         pBIHeader->biXPelsPerMeter = 0;
  412.         pBIHeader->biYPelsPerMeter = 0;
  413.         pBIHeader->biClrUsed       = 0;
  414.         pBIHeader->biClrImportant  = 0;
  415. #endif /* (else of) USE_DIB_SECTION */                                    // / _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  416. #if defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  417.         HXxRect rDestRect = { m_lXScrollOffset, m_lYScrollOffset,
  418.                 m_size.cx, m_size.cy};
  419. #else // /try #2: move the drawing of the text, not the window srcRect:
  420.         HXxRect rDestRect = {0,0, m_size.cx, m_size.cy};
  421. #endif // /XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE.
  422.  
  423. #if defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  424.         HXxRect rSrcRect  = { 0, 0,
  425.                 m_size.cx - m_lXScrollOffset, m_size.cy - m_lYScrollOffset };
  426.         if (bIsScrollingOut) // /Flip the rects:
  427.         {
  428.             rSrcRect.left = m_size.cx - m_lXScrollOffset;
  429.             rSrcRect.top = m_size.cy - m_lYScrollOffset;
  430.             rSrcRect.right = m_size.cx;
  431.             rSrcRect.bottom = m_size.cy;
  432.             rDestRect.left = 0;
  433.             rDestRect.top = 0;
  434.             rDestRect.right =  m_lXScrollOffset;
  435.             rDestRect.bottom = m_lYScrollOffset;
  436.         }
  437. #else
  438.         HXxRect rSrcRect  = {0,0, m_size.cx, m_size.cy};
  439. #endif // /End else of defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  440.         BYTE* pOutBuf = m_pDrawOutputBuffer;
  441.         // /First see if we have a scroll offset:
  442.         if (m_bDrawInNonTextScrollArea)
  443.         {
  444.             // /Draw the area in the dest that has no text scrolled into it yet:
  445. #if defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  446.             HX_ASSERT(4 == m_ulBitsPerPixel);
  447.             pOutBuf = (BYTE*)&ulBgColorARGB;
  448.             rSrcRect.left = 0;
  449.             rSrcRect.top = 0;
  450.             rSrcRect.right = 1;
  451.             rSrcRect.bottom = 1;
  452.             rDestRect.left = 0;
  453.             rDestRect.top = 0;
  454.             rDestRect.right =  m_size.cx;
  455.             rDestRect.bottom = m_size.cy;
  456. #endif // /XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE.
  457.             m_bDrawInNonTextScrollArea = FALSE;
  458.         }
  459.         pVideoSurface->Blt(pOutBuf,
  460.                pBIHeader,
  461.                rDestRect,
  462. /* XXXEH- Check retval! */               rSrcRect);
  463.     }
  464.     else
  465.     {
  466.         hxrslt = HXR_UNEXPECTED;
  467.         goto cleanup;
  468.     }
  469. cleanup:
  470.     return hxrslt;
  471. }
  472. /****************************************************************************
  473.  *  C3GPPTimedTextRenderer::SetFont                      ref:  3gppttrender.h
  474.  *
  475.  * Sets m_pFont (if it's NULL) to appropriate font by loading the closest-
  476.  * to-given-attributes font available on the system.
  477.  */
  478. HX_RESULT
  479. C3GPPTimedTextRenderer::SetFont(const C3GPPTextSampleEntry* pCurTextSampleEntry,
  480.                                 UINT16 uiFontID_override,
  481.                                 const char* pCurFontFaceString,
  482.                                 BOOL bIsBolded,
  483.                                 BOOL bIsItalicized,
  484.                                 BOOL bIsUnderlined,
  485.                                 BOOL bIsStruckThrough,
  486.                                 UINT32 ulScaledHeight
  487. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  488.                                 , DWORD fdwCharSet
  489. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  490.                                 )
  491. {
  492.     HX_ASSERT(pCurTextSampleEntry);
  493.     HX_RESULT hxrslt = HXR_OK;
  494. #if defined(_SYMBIAN)  ||  defined(_WINDOWS) // /                              -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  495. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  496.     HDC hDC = (HDC)m_pDeviceContextMemory;
  497. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  498.     UINT16 uiFontIndx = 0;
  499.     BYTE pitchAndFamily = HX_3GPPTT_DEFAULT_PITCH | HX_3GPPTT_FF_DONTCARE;
  500.     const C3GPPFontTableBox& fontTable = pCurTextSampleEntry->GetFontTable();
  501.     const char* pszFaceName = NULL;
  502. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  503.     HX_ASSERT(m_pGCOffscreen  &&  m_pScreenDevice);
  504.     if (!m_pGCOffscreen  ||  !m_pScreenDevice)
  505.     {
  506.         goto cleanup;
  507.     }
  508. #endif // /_SYMBIAN.                                                           _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  509.     // /Use 1st value in pCurTextSampleEntry's font table and try to
  510.     // create a font from that.  If that fails, use the next in the
  511.     // table and so on.  If none succeed, just use NULL font face:
  512.     for (uiFontIndx = 0; uiFontIndx < fontTable.GetEntryCount(); uiFontIndx++)
  513.     {
  514.         // /But 1st, if uiFontID_override is not invalid (see above)
  515.         // then use the font in the table whose ID matches it
  516.         if (HX_3GPPTT_INVALID_INDEX != uiFontID_override)
  517.         {
  518.             const C3GPPFontRecord* pRec = fontTable.GetFontRecord(uiFontIndx);
  519.             if (uiFontID_override != pRec->GetFontID())
  520.             {
  521.                 // /Keep looking (unless there are no more, in which case we'll
  522.                 // have to just use the default one):
  523.                 if (uiFontIndx + 1 >= fontTable.GetEntryCount())
  524.                 {
  525.                     // /First, prevent infinite looping ;-)
  526.                     uiFontID_override = HX_3GPPTT_INVALID_INDEX;
  527.                     // /Then reset uiFontIndx to 0 and go through
  528.                     // the default table in order:
  529.                     uiFontIndx = 0;
  530.                 }
  531.                 else // /Look at the next in table for matching ID:
  532.                 {
  533.                     continue;
  534.                 }
  535.             }
  536.         }
  537.         pCurFontFaceString = fontTable.GetFontRecord(uiFontIndx)->GetFontName();
  538.         if (!pCurFontFaceString  ||  0 == strlen(pCurFontFaceString))
  539.         {
  540.             continue;
  541.         }
  542.         // /Special-case handling of "Serif", "Sans-Serif",
  543.         // and "Monospace" which aren't font faces but families:
  544.         if (!stricmp(FONT_FAMILY_SERIF_STR, pCurFontFaceString))
  545.         {
  546.             // /FF_ROMAN <== serif
  547.             pitchAndFamily = HX_3GPPTT_FF_SERIF_PROPORTIONAL_PITCH;
  548.         }
  549.         else if (!stricmp(FONT_FAMILY_SANS_SERIF_STR,
  550.                 pCurFontFaceString))
  551.         {
  552.             // /sans serif ==> FF_SWISS, variable stroke width,
  553.             // no serifs:
  554.             pitchAndFamily = HX_3GPPTT_FF_SANSSERIF_PROPORTIONAL_PITCH; 
  555.         }
  556.         else if (!stricmp(FONT_FAMILY_MONOSPACE_STR,
  557.                 pCurFontFaceString))
  558.         {
  559.             // /FIXED_PITCH <== monospace (constant stroke width)
  560.             pitchAndFamily = HX_3GPPTT_FIXED_PITCH;
  561.         }
  562.         else // /Use the font face string as the font face:
  563.         {
  564.             pszFaceName = pCurFontFaceString;
  565.         }
  566. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  567.         UINT32 ulScaledWidth = 0; // /0 means use default
  568.         if (m_pFont) // /Fixes Helix Issue 656 and Helix Issue 657:
  569.         {
  570.             DeleteObject(m_pFont);
  571.             m_pFont = NULL;
  572.         }
  573.         m_pFont = CreateFont(
  574.                 (INT32)ulScaledHeight, //logical ht 
  575.                 (INT32)ulScaledWidth, // logical average character width 
  576.                 0, // angle of escapement 
  577.                 0, //base-line orientation angle (==escapement Win95)
  578.                 (bIsBolded?FW_BOLD:FW_NORMAL),
  579.                 bIsItalicized,
  580.                 bIsUnderlined,
  581.                 bIsStruckThrough,
  582.                 fdwCharSet,
  583.                 OUT_DEFAULT_PRECIS, // output precision 
  584.                 CLIP_DEFAULT_PRECIS,// clipping precision 
  585.                 DEFAULT_QUALITY,// output quality 
  586.                 pitchAndFamily,
  587.                 // /if NULL or empty string, GDI uses the first font that
  588.                 // matches the other specified attributes:
  589.                 (LPCTSTR)pszFaceName
  590.                 );
  591.         if (m_pFont)
  592.         {
  593.             m_pFontOld = (HFONT)SelectObject(hDC, m_pFont);
  594.             if (!m_pFontOld)
  595.             {
  596.                 // /XXXEH- to do: decide if we should really exit here
  597. #if !defined(USE_DIB_SECTION)
  598.                 SelectObject(hDC, hbmpOld);
  599. #endif // /USE_DIB_SECTION.
  600.                 DeleteObject(m_pFont);
  601.                 hxrslt = HXR_UNEXPECTED;
  602.                 goto cleanup;
  603.             }
  604.             break; // /This one succeeded in loading, so quit looking.
  605.         }
  606. #elif defined(_SYMBIAN)  // /                                                  ------------------------------------
  607.         TTypeface theTypeface;
  608.         if (pszFaceName)
  609.         {
  610.             TText8* pUnicodeBuf8FontFace = (TText8*)"Swiss"; //pszFaceName;
  611.             TInt length = strlen(pszFaceName);
  612.             HX_ASSERT(length <= KMaxTypefaceNameLength);
  613.             if (length > KMaxTypefaceNameLength)
  614.             {
  615.                 length = KMaxTypefaceNameLength;
  616.             }
  617.             TPtr8 ptr(pUnicodeBuf8FontFace, length, length);
  618.             ((theTypeface.iName/*TBufC<0x18>*/).Des()).Copy(ptr);
  619.         }
  620.         
  621.         theTypeface.SetIsProportional(!(HX_3GPPTT_FIXED_PITCH & pitchAndFamily));
  622.         theTypeface.SetIsSerif(HX_3GPPTT_FF_SERIF_PROPORTIONAL_PITCH & pitchAndFamily);
  623. /*
  624. Alp13
  625. alp17
  626. Alb17b
  627. Aco21
  628. LatinBold12
  629. LatinBold13
  630. LatinBold17
  631. LatinBold19
  632. LatinPlain12
  633. */
  634.         // /Handle NULL face name and/or family (which is an exception):
  635.         HX_ASSERT(pCurFontFaceString);
  636.         if (NULL == pCurFontFaceString)
  637.         {
  638.             HX_ASSERT(!pszFaceName);
  639.             // /Just use existing font if it's available:
  640.             if (!m_pFont)
  641.             {
  642.                 HX_ASSERT(m_pScreenDevice);
  643.                 _LIT(KTxtArial,"Arial");
  644.                 TFontSpec tmpFontSpec(KTxtArial, ulScaledHeight * 20);
  645.                 m_pScreenDevice->GetNearestFontInTwips(m_pFont, tmpFontSpec);
  646.             }
  647.         }
  648.         else
  649.         {
  650.             // /Load font if it's NULL.  If it's not NULL, clean it up first:
  651.             if (NULL != m_pFont)
  652.             {
  653.                 HX_ASSERT(m_pScreenDevice);
  654.                 if (m_pScreenDevice)
  655.                 {
  656.                     m_pScreenDevice->ReleaseFont(m_pFont);
  657.                 }
  658.                 m_pFont = NULL;
  659.             }         
  660.             TFontSpec theFontSpec;
  661.             theFontSpec.iTypeface = theTypeface;
  662.             theFontSpec.iHeight = ulScaledHeight * 20; // /points*20 = twips
  663.           
  664.             theFontSpec.iFontStyle.SetPosture(bIsItalicized? EPostureItalic:EPostureUpright);
  665.             theFontSpec.iFontStyle.SetStrokeWeight(bIsBolded? EStrokeWeightBold:EStrokeWeightNormal);
  666.             m_pGCOffscreen->SetUnderlineStyle(bIsUnderlined? EUnderlineOn:EUnderlineOff);
  667.             m_pScreenDevice->GetNearestFontInTwips(m_pFont, theFontSpec);  
  668.         }
  669.         if (m_pFont)
  670.         {
  671.             // /Success: use it in gc:
  672.             m_pGCOffscreen->UseFont(m_pFont);
  673. #if defined(_DEBUG)
  674.             // /XXXEH- remove this assert after verifying code is correct:
  675.             TInt tiTmp = m_pFont->HeightInPixels();
  676. //            HX_ASSERT(m_pFont->HeightInPixels() == (TInt)ulScaledHeight);
  677. #endif
  678.             break; // /This one succeeded in loading, so quit looking.
  679.         }
  680. #endif // /end else of ifdef _WINDOWS.                                         _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  681.         // /Else if we failed to load the font and we're using a
  682.         // font override, then use the default font table, in order:
  683.         else if (HX_3GPPTT_INVALID_INDEX != uiFontID_override)
  684.         {
  685.             HX_ASSERT(0); // /Should never get here, A.F.A.I.K.
  686.             // /First, prevent infinite looping ;-)
  687.             uiFontID_override = HX_3GPPTT_INVALID_INDEX;
  688.             // /Then reset uiFontIndx to 0 and go through
  689.             // the default table in order:
  690.             // /XXXEH- note: this will skip entry 0 since uiFontIndx++
  691.             // in the for loop will occur, but this is an exception
  692.             // getting here, anyway, so don't devote code to that:
  693.             uiFontIndx = 0;
  694.         }
  695.         // /else try to load the next author-suggested alternate font via for()
  696.     } // /END "for (UINT16 uiFontIndx..."
  697. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  698. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  699. if (pFile)
  700. {
  701. fprintf(pFile, "[step 3] T.C. = %p at time %lu (text containers handled = "
  702. "%ld), m_pTextContainerListFutureTimePos=%pn", pTextContainer,
  703. m_ulTimeOfLastTimeSync, ulTextContainersHandled,
  704. m_pTextContainerListFutureTimePos);
  705. fclose(pFile);
  706. }
  707. ulCount++;
  708. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  709.     // /If none in the font table could be loaded, then, uh ... quit, I guess:
  710.     if (!m_pFont)
  711.     {
  712.         HX_ASSERT(m_pFont);
  713. #if defined(_WINDOWS)  &&  !defined(USE_DIB_SECTION)
  714.         SelectObject(hDC, hbmpOld);
  715. #endif // /USE_DIB_SECTION.
  716.         hxrslt = HXR_UNEXPECTED;
  717.         goto cleanup;
  718.     }
  719. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  720. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  721. if (pFile)
  722. {
  723. fprintf(pFile, "[step 4] T.C. = %p at time %lu (text containers handled = "
  724. "%ld), m_pTextContainerListFutureTimePos=%pn", pTextContainer,
  725. m_ulTimeOfLastTimeSync, ulTextContainersHandled,
  726. m_pTextContainerListFutureTimePos);
  727. fclose(pFile);
  728. }
  729. ulCount++;
  730. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  731. #else  // /else of: _WINDOWS  ||  _SYMBIAN
  732. #pragma message("====##### This OS needs code that sets font #####====")
  733. #endif // /end else of: _WINDOWS  ||  _SYMBIAN                                 _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  734. cleanup:
  735.     return hxrslt;
  736. }
  737. /****************************************************************************
  738.  *  C3GPPTimedTextRenderer::SetJustification             ref:  3gppttrender.h
  739.  *
  740.  * Sets justification flags (to be used in each OS's version of DrawText()):
  741.  */
  742. UINT32
  743. C3GPPTimedTextRenderer::SetJustificationFlags(
  744.         const C3GPPTextSampleEntry* pCurTextSampleEntry)
  745. {
  746.     UINT32 ulTextFormatFlags = HX_3GPPTT_INITIAL_TEXTFORMAT;
  747.     switch (pCurTextSampleEntry->GetHorJust())
  748.     {
  749.         case HX_3GPPTT_JUSTIFICATION_LEFT:
  750.             ulTextFormatFlags |= HX_3GPPTT_JUSTIFY_LEFT;
  751.             break;
  752.         case HX_3GPPTT_JUSTIFICATION_CENTER:
  753.             ulTextFormatFlags |= HX_3GPPTT_JUSTIFY_HCENTER;
  754.             break;
  755.         case HX_3GPPTT_JUSTIFICATION_RIGHT:
  756.             ulTextFormatFlags |= HX_3GPPTT_JUSTIFY_RIGHT;
  757.             break;
  758.     }
  759.     switch (pCurTextSampleEntry->GetVerJust())
  760.     {
  761.         case HX_3GPPTT_JUSTIFICATION_TOP:
  762.             ulTextFormatFlags |= HX_3GPPTT_JUSTIFY_TOP;
  763.             break;
  764.         case HX_3GPPTT_JUSTIFICATION_CENTER:
  765. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  766. // /XXXEH- todo: v-align:
  767. // we need a different solution that allows for multi-line v-alignment,
  768. // which Windows doesn't do.  Symbian doesn't do any vert alignment for you,
  769. // anyway:
  770. #define XXXEH_DO_HACK_FOR_WINDOWS_VALIGN
  771. #endif // /_WINDOWS.                                                           _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  772. #if defined(XXXEH_DO_HACK_FOR_WINDOWS_VALIGN)
  773.             ulTextFormatFlags |= DT_SINGLELINE;
  774. #endif // /XXXEH_DO_HACK_FOR_WINDOWS_VALIGN
  775.             ulTextFormatFlags |= HX_3GPPTT_JUSTIFY_VCENTER;
  776.             break;
  777.         case HX_3GPPTT_JUSTIFICATION_BOTTOM:
  778. #if defined(XXXEH_DO_HACK_FOR_WINDOWS_VALIGN)
  779.             ulTextFormatFlags |= DT_SINGLELINE;
  780. #endif // /XXXEH_DO_HACK_FOR_WINDOWS_VALIGN
  781.             ulTextFormatFlags |= HX_3GPPTT_JUSTIFY_BOTTOM;
  782.             break;
  783.     }
  784.     return ulTextFormatFlags;
  785. }
  786. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  787. /****************************************************************************
  788.  *  C3GPPTimedTextRenderer::ConvertToOSRenderableChars   ref:  3gppttrender.h
  789.  *
  790.  * Takes a TextContainer's string and:
  791.  *  (a) decides if it's UTF-8 or UTF-16.  If UTF-8, converts to UTF-16.
  792.  *      e.g., "Hello" will be converted to "H e l l o "
  793.  *  (b) On Symbian, returns NULL pszNativeString if already UTF-16 string
  794.  *      otherwise returns converted-to-UTF16 string
  795.  *  (c) On Windows, converts from UTF-16 to appropriate character set.
  796.  *      e.g., "H e l l o " will be converted "Hello" and charst returned
  797.  *      will be ISO-8859-1 (ANSI_CHARSET on Windows)
  798.  *
  799.  * pszNativeString must be NULL coming in. Receiver must deleted it when done.
  800.  * NOTE: the only guaranteed NULL-terminated char buffer used in this method
  801.  * is pszNativeString (hence the others don't have psz... variable names):
  802.  */
  803. HX_RESULT
  804. C3GPPTimedTextRenderer::ConvertToOSRenderableChars(const C3GPPTextContainer* pTextCont,
  805.                                                  /*OUT*/ DWORD& fdwCharSet,
  806.                                                  /*OUT*/ char*& pszNativeString,
  807.                                                  /*OUT*/ INT32& lNativeStringLen)
  808. {
  809.     HX_ASSERT(pTextCont);
  810.     HX_RESULT hxrslt = HXR_FAIL;
  811.     INT32 lTextNumBytes = 0;
  812.     const char* pTextContainerText = NULL;
  813.     BOOL bTextContainerTextIsUTF16Encoded = FALSE;
  814.     BOOL bTextContainerTextIsUTF16ReverseEncoded = FALSE;
  815.     if (!pTextCont  ||  !pTextCont->m_pTextSample  ||
  816.             !pTextCont->m_pTextSample->GetText()  ||
  817.             pTextCont->m_pTextSample->GetTextLenInBytes() <
  818.             pTextCont->GetTextByteLength() +
  819.             pTextCont->m_uiUnpackedStartCharOffset  ||
  820.             pTextCont->m_uiUnpackedEndCharOffset <=
  821.             pTextCont->m_uiUnpackedStartCharOffset)
  822.     {
  823.         hxrslt = HXR_INVALID_PARAMETER;
  824.         HX_ASSERT(HXR_INVALID_PARAMETER != hxrslt); // /Always assert here
  825.         goto cleanup;
  826.     }
  827.     lTextNumBytes = (INT32)((UINT32)pTextCont->GetTextByteLength());
  828.     // /NOTE: this is not NULL-terminated:
  829.     pTextContainerText = (const char*)pTextCont->m_pTextSample->GetTextAt(
  830.             pTextCont->m_uiUnpackedStartCharOffset);
  831.     bTextContainerTextIsUTF16Encoded =
  832.             IsUTF16Encoded((const UCHAR*)pTextContainerText, lTextNumBytes,
  833.             /*REF*/bTextContainerTextIsUTF16ReverseEncoded);
  834.     HX_ASSERT(NULL == pszNativeString);
  835.     if (pszNativeString) // /Incoming char buf must be NULL
  836.     {
  837.         hxrslt = HXR_UNEXPECTED;
  838.     }
  839.     else
  840.     {
  841.         UINT16* pUTF16String = NULL;
  842.         INT32 lLenUTF16StrInWideChars = 0;
  843.         if (bTextContainerTextIsUTF16Encoded)
  844.         {
  845.             if (bTextContainerTextIsUTF16ReverseEncoded)
  846.             {
  847.                 // /We can just use the bytes (past the 0xFEFF flag) without
  848.                 // modification since Windows is little endian:
  849.                 pUTF16String = (UINT16*)(pTextContainerText+2);
  850.                 lLenUTF16StrInWideChars = (lTextNumBytes-2) / 2;
  851.             }
  852.             else
  853.             {
  854.                 lLenUTF16StrInWideChars = (lTextNumBytes-2) / 2;
  855.                 // /Big-endian, so we need to swap bytes into new buffer:
  856.                 pUTF16String = new UINT16[lLenUTF16StrInWideChars+1];
  857.                 if (pUTF16String)
  858.                 {
  859.                     for (UINT32 uli16=0; uli16<lLenUTF16StrInWideChars; uli16++)
  860.                     {
  861.                         pUTF16String[uli16] =
  862.                                 ((UINT16)pTextContainerText[(uli16+1)*2])<<8 |
  863.                                 pTextContainerText[((uli16+1)*2) + 1];
  864.                     }
  865.                 }
  866.             }
  867.         }
  868.         else
  869.         {
  870.             // /In Windows, we have to convert to UTF-16 and then convert
  871.             // again to a Windows renderable DBCS charset: 
  872.             // First, find the buffer length needed for the conversion:
  873.             lLenUTF16StrInWideChars = MultiByteToWideChar(  /* Flawfinder: ignore */
  874.                     CP_UTF8, 0, pTextContainerText, lTextNumBytes, NULL, 0);
  875.             pUTF16String = new UINT16 [lLenUTF16StrInWideChars];
  876.             if (!pUTF16String)
  877.             {
  878.                 hxrslt = HXR_OUTOFMEMORY;
  879.                 goto cleanup;
  880.             }
  881.             // convert UTF-8 to UTF-16
  882.             memset(pUTF16String, 0, lLenUTF16StrInWideChars); /* Flawfinder: ignore */
  883.             MultiByteToWideChar(CP_UTF8, 0,  /* Flawfinder: ignore */
  884.                     pTextContainerText, lTextNumBytes, pUTF16String,
  885.                     lLenUTF16StrInWideChars);
  886.         }
  887.         if (pUTF16String)
  888.         {
  889.             UINT32 ulCodePage = 1252; // /Init to ANSI - Latin I just for kicks
  890.             // /Now, we need to figure out what character set this is, based
  891.             // on what UTF-16 character codes it contains:
  892.             GetAppropriateCharset(pUTF16String, lLenUTF16StrInWideChars,
  893.                     /*REF*/fdwCharSet, /*REF*/ulCodePage);
  894.             INT32 lLenWinStrInBytes = WideCharToMultiByte( /* Flawfinder: ignore */
  895.                     ulCodePage, 0, pUTF16String, lLenUTF16StrInWideChars, NULL, 0, NULL, NULL);
  896.             pszNativeString = new char [lLenWinStrInBytes + 1];
  897.             if (pszNativeString)
  898.             {
  899.                 lNativeStringLen = lLenWinStrInBytes;
  900.                 // convert UTF-16 to Windows charset string:
  901.                 memset(pszNativeString, 0, lLenWinStrInBytes + 1); /* Flawfinder: ignore */
  902.                 BOOL bOoL = FALSE;
  903.                 WideCharToMultiByte(/* Flawfinder: ignore */
  904. ulCodePage,
  905.                         0, //WC_DEFAULTCHAR, // /<= convert exceptions to default char
  906.                         pUTF16String, lLenUTF16StrInWideChars,
  907.                         pszNativeString, lLenWinStrInBytes,
  908.                         NULL, // /LPCSTR lpDefaultChar, for unmappable chars
  909.                         &bOoL // /<=gets set to TRUE when default char used
  910.                         );
  911.                 hxrslt = HXR_OK;
  912.             }
  913.             if (bTextContainerTextIsUTF16ReverseEncoded)
  914.             {
  915.                 HX_VECTOR_DELETE(pUTF16String);
  916.             }
  917.         }
  918.     }
  919. cleanup:
  920.     return hxrslt;
  921. }
  922. #define HX_3GPPTT_UCHART_NUM_CHARTS  32
  923.     /* Windows defined charsets:
  924.     ANSI_CHARSET         // /iso-8859-1, us-ascii
  925.     SHIFTJIS_CHARSET     // /x-sjis
  926.     HANGEUL_CHARSET      // /hangeul
  927.     JOHAB_CHARSET        // /johab
  928.     GB2312_CHARSET       // /gb2312
  929.     CHINESEBIG5_CHARSET  // /big5, x-euc-tw
  930.     EASTEUROPE_CHARSET   // /iso-8859-2
  931.     RUSSIAN_CHARSET      // /iso-8859-5, windows-1251
  932.     ARABIC_CHARSET       // /iso-8859-6
  933.     GREEK_CHARSET        // /iso-8859-7
  934.     HEBREW_CHARSET       // /iso-8859-8
  935.     TURKISH_CHARSET      // /iso-8859-9
  936.     THAI_CHARSET         // /iso-8859-11, iso-ir-166
  937.     BALTIC_CHARSET       // /iso-8859-13
  938.     */
  939. static const UINT32 HX_3GPPTT_UCHART_START_INDICES[HX_3GPPTT_UCHART_NUM_CHARTS] =
  940.     {
  941.         0x0041, 0x00C0, 0x1D00, 0x1E00, 0xFB00, // /Latin
  942.         0x0370, 0x1F00,  // /Greek
  943.         0x0400, 0x0500, // /Cyrillic
  944.         0x0530, // /Armenian (EASTEUROPE_CHARSET???)
  945.         0x10A0, // /Georgian (EASTEUROPE_CHARSET???)
  946.         0x0590, 0xFB1D, // /Hebrew
  947.         0x0600, 0xFB50, 0xFE70, // /Arabic
  948.         0x0E00, // /Thai
  949.         0x20000, 0xF900, 0x2F800, 0x3190, 0x2E80, 0x2FF0, // /Han (CJK)
  950.         0x3100, // /Bopomofo  (Chinese zh鵼inf鷋鄌 (still in use in Taiwan))
  951.         0x3040, 0x30A0, 0x31F0, 0xFF00, // /Hiragana and Katakana (Japanese)
  952.         0x1100, 0x3130, 0xAC00, // /Hangeul (Korean)
  953.         0xA000 // /Yi  (???)
  954.     };
  955. static const UINT32 HX_3GPPTT_UCHART_END_INDICES[HX_3GPPTT_UCHART_NUM_CHARTS] =
  956.     {
  957.         0x007A, 0x02AF, 0x1D6A, 0x1EFF, 0xFB06, // /Latin
  958.         0x03FF, 0x1FFF,  // /Greek
  959.         0x04FF, 0x052F, // /Cyrillic
  960.         0x058F, // /Armenian (EASTEUROPE_CHARSET???)
  961.         0x10FF, // /Georgian (EASTEUROPE_CHARSET???)
  962.         0x05FF, 0xFB4F, // /Hebrew
  963.         0x06FF, 0xFDFF, 0xFEFF, // /Arabic
  964.         0x0E7F, // /Thai
  965.         0x2A6D6, 0xFAFF, 0x2FA1D, 0x319F, 0x2FD5, 0x2FFB, // /Han (CJK)
  966.         0x312F, // /Bopomofo  (Chinese zh鵼inf鷋鄌 (still in use in Taiwan))
  967.         0x309F, 0x30FF, 0x31FF, 0xFFEF, // /Hiragana and Katakana (Japanese)
  968.         0x11FF, 0x318F, 0xD7A3, // /Hangeul (Korean)
  969.         0xA4CF, // /Yi  (???)  
  970.     };
  971. /****************************************************************************
  972.  *  C3GPPTimedTextRenderer::GetAppropriateCharset        ref:  3gppttrender.h
  973.  *
  974.  *  Windows-only method that looks at the contents of a wide-char string to
  975.  *  decide (best-guess) what Windows charset it is
  976.  */
  977. HX_RESULT
  978. C3GPPTimedTextRenderer::GetAppropriateCharset(wchar_t* pUTF16String,
  979.         INT32 lLenUTF16StrInWideChars,
  980.         /*OUT*/ DWORD& fdwCharSet, /*OUT*/UINT32& ulCodePage)
  981. {
  982.     HX_RESULT hxrslt = HXR_OK;
  983.     UINT32 ulLastCharChartIndex = 0;
  984.     UINT32 uljj = 0;
  985.     UINT32 ulii = 0;
  986.     UINT32 ulIndexOfMax = 0;
  987.     UINT32 ulMaxFound = 0;
  988.     UINT16 pCountArray[HX_3GPPTT_UCHART_NUM_CHARTS];
  989.     memset(pCountArray, 0x0, HX_3GPPTT_UCHART_NUM_CHARTS*sizeof(UINT16));
  990.     if (!pUTF16String  ||  lLenUTF16StrInWideChars<1)
  991.     {
  992.         hxrslt = HXR_UNEXPECTED;
  993.         goto cleanup;
  994.     }
  995.     // /Init to ANSI Latin 1:
  996.     fdwCharSet = ANSI_CHARSET;
  997.     ulCodePage = 1252; // / ANSI - Latin I
  998.     // /Now, walk through the string and find the first non-Latin-1 char,
  999.     // if any:
  1000.     for (ulii=0; ulii<(UINT32)lLenUTF16StrInWideChars; ulii++)
  1001.     {
  1002.         if (ulii > 0  &&  pUTF16String[ulii] >=
  1003.                 HX_3GPPTT_UCHART_START_INDICES[ulLastCharChartIndex]  &&
  1004.                 pUTF16String[ulii] <=
  1005.                 HX_3GPPTT_UCHART_END_INDICES[ulLastCharChartIndex])
  1006.         {
  1007.             // /Optimization in search: assume prior character is most likely
  1008.             // in same UNICODE area as this one; if not, then do for() below:
  1009.             pCountArray[ulLastCharChartIndex]++;
  1010.             continue;
  1011.         }
  1012.         for (uljj=0; uljj<HX_3GPPTT_UCHART_NUM_CHARTS; uljj++)
  1013.         {
  1014.             if (pUTF16String[ulii] >= HX_3GPPTT_UCHART_START_INDICES[uljj]  &&
  1015.                     pUTF16String[ulii] <= HX_3GPPTT_UCHART_END_INDICES[uljj])
  1016.             {
  1017.                 ulLastCharChartIndex = uljj;
  1018.                 pCountArray[uljj]++;
  1019.                 break;
  1020.             }
  1021.         }
  1022.     }
  1023.     // /Now, look at the largest user and guess that we've found the charset:
  1024.     for (uljj=0; uljj<HX_3GPPTT_UCHART_NUM_CHARTS; uljj++)
  1025.     {
  1026.         if (pCountArray[uljj] > ulMaxFound)
  1027.         {
  1028.             ulMaxFound = pCountArray[uljj];
  1029.             ulIndexOfMax = uljj;
  1030.         }
  1031.     }
  1032.     if (ulIndexOfMax < 5)
  1033.     {
  1034.         fdwCharSet = ANSI_CHARSET;    // /~iso-8859-1
  1035.         ulCodePage = 1252;            // / ANSI - Latin I
  1036.     }
  1037.     else if (ulIndexOfMax < 7)
  1038.     {
  1039.         fdwCharSet = GREEK_CHARSET;   // /~iso-8859-7
  1040.         ulCodePage = 1253;            // / ANSI - Greek
  1041.     }
  1042.     else if (ulIndexOfMax < 9)
  1043.     {
  1044.         fdwCharSet = RUSSIAN_CHARSET; // /~iso-8859-5, windows-1251
  1045.         ulCodePage = 1251;            // / ANSI - Cyrillic
  1046.     }
  1047.     else if (ulIndexOfMax < 10)
  1048.     {
  1049.         fdwCharSet = EASTEUROPE_CHARSET; // /~iso-8859-2
  1050.         ulCodePage = 1250;               // / ANSI - Central European
  1051.     }
  1052.     else if (ulIndexOfMax < 11)
  1053.     {
  1054.         fdwCharSet = EASTEUROPE_CHARSET; // /~iso-8859-2
  1055.         ulCodePage = 1250;               // / ANSI - Central European
  1056.     }
  1057.     else if (ulIndexOfMax < 13)
  1058.     {
  1059.         fdwCharSet = HEBREW_CHARSET; // /~iso-8859-8
  1060.         ulCodePage = 1255;           // / ANSI - Hebrew
  1061.     }
  1062.     else if (ulIndexOfMax < 16)
  1063.     {
  1064.         fdwCharSet = ARABIC_CHARSET; // /~iso-8859-6
  1065.         ulCodePage = 1256;           // / ANSI - Arabic
  1066.     }
  1067.     else if (ulIndexOfMax < 17)
  1068.     {
  1069.         fdwCharSet = THAI_CHARSET;   // /~iso-8859-11, ~iso-ir-166
  1070.         ulCodePage = 874;            // / ANSI/OEM - Thai (same as 28605,
  1071.                                      //              ISO 8859-15)
  1072.     }
  1073.     else if (ulIndexOfMax < 23)
  1074.     {
  1075.         // /XXXEH- this is CJK unified, so we don't know if it's Chinese,
  1076.         // Japanese, or Korean unless we study the actual text.  Assume
  1077.         // Japanese if any Hirigana or Katakana were present, Hangeul if
  1078.         // any Hangeul were present, and Chinese if Yi (???) were present
  1079.         // otherwise Japanese:
  1080.         if (pCountArray[24]  ||  pCountArray[25]  ||  pCountArray[26]  ||
  1081.                 pCountArray[27])
  1082.         {
  1083.             fdwCharSet = SHIFTJIS_CHARSET; // /~x-sjis
  1084.             ulCodePage = 932;              // / ANSI/OEM - Japanese, Shift-JIS
  1085.         }
  1086.         else if (pCountArray[28]  ||  pCountArray[29]  ||  pCountArray[30])
  1087.         {
  1088.             fdwCharSet = HANGEUL_CHARSET; // /~hangeul
  1089.             ulCodePage = 949;             // / ANSI/OEM - Korean (Unified Hangeul)
  1090.         }
  1091.         else if (pCountArray[31])
  1092.         {
  1093.             fdwCharSet = GB2312_CHARSET; // /Yi ??? XXXEH- or could be Big5
  1094.             ulCodePage = 936;            // / ANSI/OEM - Simplified Chinese
  1095.                                          //              (PRC, Singapore)
  1096.         }
  1097.         else
  1098.         {
  1099.             fdwCharSet = SHIFTJIS_CHARSET; // /~x-sjis
  1100.             ulCodePage = 932;              // / ANSI/OEM - Japanese, Shift-JIS
  1101.         }
  1102.     }
  1103.     else if (ulIndexOfMax < 24)
  1104.     {
  1105.         fdwCharSet = CHINESEBIG5_CHARSET; // /Bopomofo (Taiwan: Trad'l Chinese)
  1106.         ulCodePage = 950;                 // / ANSI/OEM - Traditional Chinese
  1107.                                           //       (Taiwan; Hong Kong SAR, PRC)
  1108.     }
  1109.     else if (ulIndexOfMax < 28)
  1110.     {
  1111.         fdwCharSet = SHIFTJIS_CHARSET; // /~x-sjis
  1112.         ulCodePage = 932;              // / ANSI/OEM - Japanese, Shift-JIS
  1113.     }
  1114.     else if (ulIndexOfMax < 31)
  1115.     {
  1116.         fdwCharSet = HANGEUL_CHARSET;  // /~hangeul
  1117.         ulCodePage = 949;              // / ANSI/OEM - Korean (Unified Hangeul)
  1118.     }
  1119.     else if (ulIndexOfMax < 32)
  1120.     {
  1121.         fdwCharSet = GB2312_CHARSET; // /Yi ???  XXXEH- or could be Big5
  1122.         ulCodePage = 936;            // / ANSI/OEM - Simplified Chinese
  1123.                                      //              (PRC, Singapore)
  1124.     }
  1125.     else
  1126.     {
  1127.         HX_ASSERT(ulIndexOfMax < HX_3GPPTT_UCHART_NUM_CHARTS);
  1128.         fdwCharSet = ANSI_CHARSET;
  1129.         ulCodePage = 1252;            // / ANSI - Latin I
  1130.     }
  1131. cleanup:
  1132.     return hxrslt;
  1133. }
  1134. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1135. /****************************************************************************
  1136.  *  C3GPPTimedTextRenderer::FillRectangle                ref:  3gppttrender.h
  1137.  *
  1138.  */
  1139. HX_RESULT
  1140. C3GPPTimedTextRenderer::FillRectangle(UINT32 ulRectColorARGB)
  1141. {
  1142.     HX_RESULT hxrslt = HXR_UNEXPECTED;
  1143.     if (m_pDrawOutputBuffer  &&  m_ulDrawOutputBufferSizeInBytes)
  1144.     {
  1145. #if (HX_3GPPTT_DEFAULT_bits_PER_PIXEL == 32)
  1146.         HX_ASSERT(m_ulBitsPerPixel >= 8);
  1147.         // /XXXEH- todo: take into account the (possibly-smaller-than-region) rect of this entry:
  1148.         UINT32 ulNumPixelsHandled = 0;
  1149.         UINT32 ulNumPixelsTotal = m_ulDrawOutputBufferSizeInBytes/(m_ulBitsPerPixel/8);
  1150.         UINT32* pCurPixel = (UINT32*)m_pDrawOutputBuffer;
  1151.         for ( ; ulNumPixelsHandled < ulNumPixelsTotal; pCurPixel++)
  1152.         {
  1153.             *pCurPixel = ulRectColorARGB;
  1154.             ulNumPixelsHandled++;
  1155.         }
  1156.         hxrslt = HXR_OK;
  1157. #elif defined(_SYMBIAN) // /                                                   -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1158.         if (m_pGCOffscreen)
  1159.         {
  1160.             TRgb rgbColor;
  1161.             convertARGBtoSymbianTrgbColor(rgbColor, ulRectColorARGB);
  1162.             m_pGCOffscreen->SetPenStyle(CGraphicsContext::ENullPen);
  1163.             m_pGCOffscreen->SetBrushStyle(CGraphicsContext::ESolidBrush);
  1164.             m_pGCOffscreen->SetBrushColor(rgbColor);
  1165.             const TRect theRect(0, 0, m_size.cx, m_size.cy);
  1166.             m_pGCOffscreen->DrawRect(theRect);
  1167.             // /Set pen & brush back to what they were for text drawing:
  1168.             m_pGCOffscreen->SetPenStyle(CGraphicsContext::ESolidPen);
  1169.             m_pGCOffscreen->SetBrushStyle(CGraphicsContext::ENullBrush);
  1170.         }
  1171. #else // /                                                                     ------------------------------------
  1172. #error: FillRectangle() not implemented for this bitdepth &/or platform
  1173. #endif// /#if HX_3GPPTT_DEFAULT_bits_PER_PIXEL == 32, #elif _SYMBIAN, #else... _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1174.     }
  1175.     return hxrslt;
  1176. }
  1177. /****************************************************************************
  1178.  *  C3GPPTimedTextRenderer::HandleClick                  ref:  3gppttrender.h
  1179.  *
  1180.  */
  1181. HX_RESULT
  1182. C3GPPTimedTextRenderer::HandleClick(INT16 fwKeys, INT16 xPos, INT16 yPos)
  1183. {
  1184.     HX_RESULT hxrslt = HXR_OK;
  1185.     m_ulNumberOfClicks++;
  1186.     if (m_pHyperNavigate)
  1187.     {
  1188.         C3GPPTextHyperTextBox* pHyperTextBox =
  1189.                 findActiveHyperlinkAtXY(xPos, yPos);
  1190.         
  1191. if (pHyperTextBox)
  1192.         {
  1193.             const char* pszURL = pHyperTextBox->GetURL();
  1194.             if( pszURL && *pszURL != '')
  1195.             {
  1196.                 // launching URLs usually replaces the current presentation):
  1197.                 m_pHyperNavigate->GoToURL(pszURL,
  1198.             NULL /* NULL= use default target (default browser) */);
  1199.         
  1200.             }
  1201. }
  1202.     }
  1203.     return hxrslt;
  1204. }
  1205. /****************************************************************************
  1206.  *  C3GPPTimedTextRenderer::OnMouseMove                  ref:  3gppttrender.h
  1207.  *
  1208.  */
  1209. BOOL
  1210. C3GPPTimedTextRenderer::OnMouseMove(INT16 fwKeys, INT16 xPos, INT16 yPos)
  1211. {
  1212.     // don't do anything if the x/y coordinates have changed from the
  1213.     // last call to OnMouseMove - this is needed because the call to
  1214.     // IHXStatusMessage::SetStatus() results in a WM_MOUSEMOVE event
  1215.     if(xPos == m_nLastMouseMoveXPos  &&
  1216.             yPos == m_nLastMouseMoveYPos)
  1217.     {
  1218.         return FALSE;
  1219.     }
  1220.     m_nLastMouseMoveXPos = xPos;
  1221.     m_nLastMouseMoveYPos = yPos;
  1222. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1223.     HCURSOR hCurrentCursor = GetCursor();
  1224. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1225.     C3GPPTextHyperTextBox* pHyperTextBox =
  1226.             findActiveHyperlinkAtXY(xPos, yPos);
  1227.     if (pHyperTextBox && pHyperTextBox->HasURL())
  1228.     {
  1229.         const char* pszURL = pHyperTextBox->GetURL();
  1230.         HX_ASSERT(pszURL && *pszURL != '');
  1231.         
  1232.     
  1233. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1234.         if(!m_hHyperlinkCursor)
  1235.         {
  1236.             m_hHyperlinkCursor = LoadCursor(g_hInstance, 
  1237.                     MAKEINTRESOURCE(HANDCURSOR));
  1238.             if(!m_hHyperlinkCursor)
  1239.             {
  1240.                 m_hHyperlinkCursor=LoadCursor(NULL, IDC_UPARROW);
  1241.             }
  1242.         }
  1243.         if(m_hHyperlinkCursor  &&
  1244.                 hCurrentCursor != m_hHyperlinkCursor)
  1245.         {
  1246.             //Change it; we just moved onto a hyperlink:
  1247.             //Handle this in WM_SETCURSOR (which should arrive
  1248.             // shortly):
  1249.             m_bNeedToSetHyperlinkHandCursor = TRUE;
  1250.         }
  1251.         //Note: if needed, Window Handle is m_pEvent->window.
  1252. #elif defined(_MACINTOSH)
  1253.         if (m_hHyperlinkCursor)
  1254.         {
  1255.             ::SetCursor(*m_hHyperlinkCursor);
  1256.             m_CurrentCursor = CURSOR_HYPERLINK;
  1257.         }
  1258. #elif defined(_UNIX) && (!(defined(_BEOS)))
  1259.         if (!m_hHyperlinkCursor && m_pPixmapDisplay && m_lastWindow)
  1260.         {
  1261.             m_hHyperlinkCursor = XCreateFontCursor(m_pPixmapDisplay, 
  1262.                     XC_hand2);
  1263.         }
  1264.         if (m_hHyperlinkCursor)
  1265.         {
  1266.             XDefineCursor(m_pPixmapDisplay, m_lastWindow, m_hHyperlinkCursor);
  1267.             m_bHandActivated = TRUE;
  1268.         }
  1269. #endif // /_WINDOWS -else- _MACINTOSH -else- (_UNIX && !_BEOS)                 _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1270. #if defined(HELIX_3GPPTT_USE_STATUS_BAR)
  1271.         if (m_pStatusMessage)
  1272.         {
  1273.             const char* pszDisplayURL  = pszURL;
  1274.             
  1275.             // /If Alt URL is set, then use it instead in the status area:
  1276.             if (pHyperTextBox->HasAltURL())
  1277.             {
  1278.                 pszDisplayURL  = pHyperTextBox->GetAltURL();
  1279.                 HX_ASSERT(pszDisplayURL && *pszDisplayURL != '');
  1280.             }
  1281.             
  1282.             if( !m_pszHLinkToDisplay || (0 != strcmp(pszDisplayURL, m_pszHLinkToDisplay)))
  1283.             {
  1284.                 // we have a new url; copy display url 
  1285.                 HX_DELETE(m_pszHLinkToDisplay);
  1286.             
  1287.                 UINT32 uDisplayURLlen = strlen(pszDisplayURL);
  1288.                 m_pszHLinkToDisplay = new char[uDisplayURLlen + 1];
  1289.                 if (!m_pszHLinkToDisplay)
  1290.                 {
  1291.                     return FALSE; // /Out of memory
  1292.                 }
  1293.                 HX_ASSERT(uDisplayURLlen <= MAX_3GPPTT_URL_LEN);
  1294.                 
  1295.                 memcpy(m_pszHLinkToDisplay,  /* Flawfinder: ignore */
  1296.                         pszDisplayURL, uDisplayURLlen);
  1297.                 m_pszHLinkToDisplay[uDisplayURLlen] = '';
  1298.             
  1299.                 m_bStatusMsgWillNeedErasing = TRUE;
  1300.                 m_pStatusMessage->SetStatus(m_pszHLinkToDisplay);
  1301.             }
  1302.         
  1303.         }
  1304. #endif /* HELIX_3GPPTT_USE_STATUS_BAR */
  1305.         return TRUE;
  1306.         
  1307.     }
  1308.     else
  1309.     {
  1310. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1311.         if(hCurrentCursor == m_hHyperlinkCursor)
  1312.         {
  1313.             //We need to change it back -- we just moved off of a hyperlink:
  1314.             //Handle this in WM_SETCURSOR (which should arrive
  1315.             // shortly):
  1316.             m_bNeedToSetHyperlinkHandCursor = FALSE;
  1317.         }
  1318. #elif defined(_MACINTOSH)
  1319.         if (m_CurrentCursor == CURSOR_HYPERLINK)
  1320.         {
  1321.             InitCursor();
  1322.             m_CurrentCursor = CURSOR_ARROW;
  1323.         }
  1324. #elif defined(_UNIX) && (!(defined(_BEOS)))
  1325.         if (m_bHandActivated)
  1326.         {
  1327.             XUndefineCursor(m_pPixmapDisplay, m_lastWindow);
  1328.             m_bHandActivated = FALSE;
  1329.         }
  1330. #endif // /_WINDOWS -else- _MACINTOSH -else- (_UNIX && !_BEOS)                 _____^^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1331. #if defined(HELIX_3GPPTT_USE_STATUS_BAR)
  1332.         if (m_pStatusMessage  &&
  1333.                 // /Only set this to NULL if we
  1334.                 // have recently set the status message, otherwise we may
  1335.                 // cause SMIL's (or other presentation-parent's) setting of the
  1336. // status message to be overwritten with NULL, i.e., erased:
  1337.                 m_bStatusMsgWillNeedErasing)
  1338.         {
  1339.             m_bStatusMsgWillNeedErasing = FALSE;
  1340.             m_pStatusMessage->SetStatus(NULL);
  1341.         }
  1342. #endif /* HELIX_3GPPTT_USE_STATUS_BAR */
  1343.         return FALSE;
  1344.     }
  1345.     return FALSE;
  1346. }
  1347. /****************************************************************************
  1348.  *  C3GPPTimedTextRenderer::findActiveHyperlinkAtXY
  1349.  *
  1350.  *  This looks through the textContainers to see if any are time-active at
  1351.  *  and hyperlinked at the specified location.  Returns NULL if none found.
  1352.  */
  1353. C3GPPTextHyperTextBox*
  1354. C3GPPTimedTextRenderer::findActiveHyperlinkAtXY(
  1355.         INT16 iXPos, INT16 iYPos)
  1356. {
  1357.     C3GPPTextHyperTextBox* pRetHyperTextBox = NULL;
  1358.     // /Look at current TextContainer of m_pTextContainerList (which is at
  1359.     // [m_pTextContainerListFutureTimePos - 1] and return its href URL, if any:
  1360.     if (m_pTextContainerList)
  1361.     {
  1362.         LISTPOSITION pListPosTmp = NULL;
  1363.         C3GPPTextContainer* pCurTextContainer = NULL;
  1364.         if (!m_pTextContainerListFutureTimePos)
  1365.         {
  1366.             // /No future-begin TextContainer, so get last one received which
  1367.             // should be currently active:
  1368.             pListPosTmp = m_pTextContainerList->GetTailPosition();
  1369.             pCurTextContainer = (C3GPPTextContainer*)
  1370.                     m_pTextContainerList->GetAt(pListPosTmp);
  1371.             HX_ASSERT(pCurTextContainer  &&
  1372.                     pCurTextContainer->GetBeginTime() <= m_ulTimeOfLastTimeSync);
  1373.         }
  1374.         else
  1375.         {
  1376.             // /Get latest non-future-begin packet:
  1377.             pListPosTmp = m_pTextContainerListFutureTimePos;
  1378.             pCurTextContainer = (C3GPPTextContainer*)
  1379.                     m_pTextContainerList->GetAtPrev(pListPosTmp);
  1380.             if (pListPosTmp)
  1381.             {
  1382.                 // /Make sure we didn't change m_pTextContainerListFutureTimePos:
  1383.                 HX_ASSERT(pListPosTmp != m_pTextContainerListFutureTimePos);
  1384.             }
  1385.         }
  1386.         HX_ASSERT(pCurTextContainer);
  1387.         if (pCurTextContainer  &&
  1388.                 // /XXXEH- handle possible time-offset!:
  1389.                 pCurTextContainer->GetBeginTime() <= m_ulTimeOfLastTimeSync  &&
  1390.                 pCurTextContainer->IsHyperlinked()  &&
  1391.                 pCurTextContainer->ContainsPoint(iXPos, iYPos) )
  1392.         {
  1393.             pRetHyperTextBox = pCurTextContainer->m_pTextHyperTextBox;
  1394.         }
  1395.     }
  1396.     return pRetHyperTextBox;
  1397. }
  1398. /****************************************************************************
  1399.  *  C3GPPTimedTextRenderer::GetPacketContentTime(IHXPacket* pNewPacket)
  1400.  *
  1401.  */
  1402. UINT32
  1403. C3GPPTimedTextRenderer::GetPacketContentTime(IHXPacket* pPacket)
  1404. {
  1405.     UINT32 ulPacketContentsBeginTime = HX_3GPPTT_INVALID_TIME;
  1406.     if (pPacket)
  1407.     {
  1408.         if (!m_bRTPPacketTested)
  1409.         {
  1410.             m_bRTPPacketTested = TRUE;
  1411.             IHXRTPPacket* pRTPPacket = NULL;
  1412.             m_bUsesRTPPackets = (pPacket->QueryInterface(IID_IHXRTPPacket,
  1413.                     (void**) &pRTPPacket) 
  1414.                     == HXR_OK);
  1415.             HX_RELEASE(pRTPPacket);
  1416.         }
  1417.         if (m_bUsesRTPPackets)
  1418.         {
  1419.             ulPacketContentsBeginTime = ((IHXRTPPacket*)pPacket)->GetRTPTime();
  1420.         }
  1421.         else
  1422.         {
  1423.             ulPacketContentsBeginTime = pPacket->GetTime();
  1424.         }
  1425.     }
  1426.     return ulPacketContentsBeginTime;
  1427. }
  1428. /****************************************************************************
  1429.  *  C3GPPTimedTextRenderer::HandleNewText(IHXPacket* pNewPacket)
  1430.  *
  1431.  *  This creates n TextContainers, each of which pt to the packet,
  1432.  *  and it AddRef's the packet in each one's ctor and then fills the
  1433.  *  m_pTextContainerList with all the new textContainer ptrs (sorted
  1434.  *  chronologically):
  1435.  */
  1436. HX_RESULT
  1437. C3GPPTimedTextRenderer::HandleNewText(IHXPacket* pNewPacket,
  1438.                                       LISTPOSITION& plistPosOfFirstTxtCntnr)
  1439. {
  1440.     HX_ASSERT(pNewPacket);
  1441.     HX_RESULT hxrslt = HXR_OK;
  1442.     IHXBuffer* pBuff = NULL;
  1443.     if (pNewPacket  &&  NULL != (pBuff = pNewPacket->GetBuffer()))
  1444.     {
  1445.         UINT32 ulPacketContentsBeginTime = GetPacketContentTime(pNewPacket);
  1446.         // /Walk through the textModifiers, if any, of the packet and break
  1447.         // text into textContainers, each pointing to the start of same-
  1448.         // attributed text blocks.  For instance, if chars [0]-[3] had
  1449.         // defaulted attributes (say black color, plain, ..etc.), [4]-[8] were
  1450.         // changed to red color, chars [7]-[10] were changed to BOLD, and
  1451.         // chars [11]-[20] had defaulted attributes, then chars [0]-[3] would
  1452.         // be in T.C. #1, [4]-[6] would be in T.C. #2, [7]-[8] would be in
  1453.         // T.C. #3, [9]-[10] would be in T.C. #4, and [11]-[20] would be in
  1454.         // T.C. #5.  Each of those 5 T.C.'s would point into the same packet.
  1455.         UINT16 uiStartCharOffset    = 0;
  1456.         UINT16 uiREFIndexOfLastChar = HX_3GPPTT_INVALID_INDEX;
  1457.         BOOL bIsFirstTextContainerFromNewPkt = TRUE;
  1458.         C3GPPTextContainer* pNewTextContainer = new C3GPPTextContainer();
  1459.         if(!pNewTextContainer)
  1460.         {
  1461.             hxrslt = HXR_OUTOFMEMORY;
  1462.             goto exit;
  1463.         }
  1464.         hxrslt = pNewTextContainer->Init(pNewPacket, ulPacketContentsBeginTime,
  1465.                 // /Set end to stream end time; we won't know this pkt's end
  1466.                 // time until next pkt arrives, unless this is last pkt in
  1467.                 // which case end time *is* the stream duration:
  1468.                 m_ulDuration,
  1469.                 uiStartCharOffset, uiREFIndexOfLastChar);
  1470.         if(FAILED(hxrslt))
  1471.         {
  1472.             HX_DELETE(pNewTextContainer);
  1473.             goto exit;
  1474.         }
  1475.         while (pNewTextContainer  &&  pNewTextContainer->m_pTextSample)
  1476.         {
  1477.             m_pTextContainerList->AddTail((void*) pNewTextContainer);
  1478.             if (bIsFirstTextContainerFromNewPkt)
  1479.             {
  1480.                 plistPosOfFirstTxtCntnr = m_pTextContainerList->GetTailPosition();
  1481.             }
  1482.             if (uiREFIndexOfLastChar <
  1483.                     pNewTextContainer->m_pTextSample->GetTextLenInBytes())
  1484.             {
  1485.                 // /Don't add 1 here; it's end-point exclusive:
  1486.                 uiStartCharOffset = uiREFIndexOfLastChar;
  1487.                 pNewTextContainer = new C3GPPTextContainer();
  1488.                 if(!pNewTextContainer)
  1489.                 {
  1490.                     hxrslt = HXR_OUTOFMEMORY;
  1491.                     break;
  1492.                 }
  1493.                 hxrslt = pNewTextContainer->Init(pNewPacket,
  1494.                         ulPacketContentsBeginTime, m_ulDuration /*=for max end time*/,
  1495.                         uiStartCharOffset, /*REF*/ uiREFIndexOfLastChar);
  1496.                 if(FAILED(hxrslt))
  1497.                 {
  1498.                     HX_DELETE(pNewTextContainer);
  1499.                     break;
  1500.                 }
  1501.                 // /Make sure we advanced; if not, something's whack:
  1502.                 HX_ASSERT(uiREFIndexOfLastChar > uiStartCharOffset);
  1503.                 if (uiREFIndexOfLastChar <= uiStartCharOffset)
  1504.                 {
  1505.                     HX_DELETE(pNewTextContainer);
  1506.                     break; // /Shaggy: "Let's get outta here Scooby!"
  1507.                 }
  1508.             }
  1509.             else
  1510.             {
  1511.                 break; // /We're done splitting text up into textContainers
  1512.             }
  1513.             bIsFirstTextContainerFromNewPkt = FALSE;
  1514.         }
  1515.     }
  1516.     else
  1517.     {
  1518.         hxrslt = HXR_INVALID_PARAMETER;
  1519.     }
  1520. exit:
  1521.     return hxrslt;
  1522. }
  1523. // /Now go through prior packet's T.C.'s and establish their
  1524. // end times (which is prior packet's content time ):
  1525. HX_RESULT
  1526. C3GPPTimedTextRenderer::SetPriorPacketTCsEndTimes()
  1527. {
  1528.     HX_RESULT hxrslt = HXR_UNEXPECTED;
  1529.     if (m_pTextContainerList)
  1530.     {
  1531.         UINT32 ulEndTime = GetPacketContentTime(m_pLatestPacket);
  1532.         LISTPOSITION pos = m_pTextContainerList->GetHeadPosition();
  1533.         while (pos)
  1534.         {
  1535.             C3GPPTextContainer* pTextContainer =
  1536.                     (C3GPPTextContainer*)m_pTextContainerList->GetNext(pos);
  1537.             HX_ASSERT(pTextContainer);
  1538.             if (pTextContainer)
  1539.             {
  1540.                 if (pTextContainer->m_pPacket == m_pLatestPacket)
  1541.                 {
  1542.                     break; // /We're done w/prior pkt's T.C.(s)
  1543.                 }
  1544.                 // /It's initialized to stream's m_ulDuration so
  1545.                 // it's not set, yet, if it equals that:
  1546.                 if (m_ulDuration <= pTextContainer->GetEndTime() )
  1547.                 {
  1548.                     pTextContainer->m_ulEndTime = ulEndTime;
  1549.                     HX_ASSERT(pTextContainer->m_ulEndTime > pTextContainer->m_ulBeginTime);
  1550.                     if (pTextContainer->m_ulEndTime <= pTextContainer->m_ulBeginTime)
  1551.                     {
  1552.                         pTextContainer->m_ulEndTime = pTextContainer->m_ulBeginTime + 1;
  1553.                     }
  1554.                 }
  1555.             }
  1556.         }
  1557.     }
  1558.     return hxrslt;
  1559. }
  1560. // /#define DEBUG_OUT_REDRAWLIST_ACTIVITY
  1561. #if defined(DEBUG_OUT_REDRAWLIST_ACTIVITY)
  1562. #pragma message("====##### undef DEBUG_OUT_REDRAWLIST_ACTIVITY from source tree! #####====")
  1563. static int icount = 0;
  1564. #endif // /DEBUG_OUT_REDRAWLIST_ACTIVITY.
  1565. HX_RESULT
  1566. C3GPPTimedTextRenderer::InsertInRedrawListInTemporalOrder(
  1567.         const C3GPPTextContainer* pTextContainer)
  1568. {
  1569. #if defined(DEBUG_OUT_REDRAWLIST_ACTIVITY)
  1570. FILE* pDrawFile = fopen("c:\3gppttInsertIntoRedrawList.txt", icount?"a+":"w");
  1571. if (pDrawFile)
  1572. {
  1573.     fprintf(pDrawFile, "at time %lutinserting %p tbegin=%lutend=%lut"
  1574.         "prevActivityTime=%lutNextActivityTime=%lun",
  1575.         m_ulTimeOfLastTimeSync, pTextContainer, pTextContainer->GetBeginTime(),
  1576.         pTextContainer->GetEndTime(), pTextContainer->GetPrevActivityTime(),
  1577.         pTextContainer->GetNextActivityTime());
  1578.     fclose(pDrawFile);
  1579.     icount++;
  1580. }
  1581. #endif // /DEBUG_OUT_REDRAWLIST_ACTIVITY.
  1582.     HX_RESULT hxrslt = HXR_OK;
  1583.     if (!m_pTextContainerRedrawList)
  1584.     {
  1585.         m_pTextContainerRedrawList = new CHXSimpleList();
  1586.         if (!m_pTextContainerRedrawList)
  1587.         {
  1588.             hxrslt = HXR_OUTOFMEMORY;
  1589.             goto cleanup;
  1590.         }
  1591.     }
  1592.     // /First, find it and remove it if it's already in there:
  1593.     RemoveFromRedrawList(pTextContainer);
  1594.     if (pTextContainer->GetEndTime() > pTextContainer->GetNextActivityTime())
  1595.     {
  1596.         // /XXXEH- todo: need to look through list and insert temporally; ties are
  1597.         // resolved by making sure that earlier-start-char-index one is first:
  1598.         m_pTextContainerRedrawList->AddTail((void*)pTextContainer);
  1599. #if defined(DEBUG_OUT_REDRAWLIST_ACTIVITY)
  1600. pDrawFile = fopen("c:\3gppttInsertIntoRedrawList.txt", icount?"a+":"w");
  1601. if (pDrawFile)
  1602. {
  1603.     fprintf(pDrawFile, "t--inserting %p into list.n",
  1604.         m_ulTimeOfLastTimeSync, pTextContainer->GetBeginTime(),
  1605.         pTextContainer->GetEndTime(), pTextContainer->GetNextActivityTime());
  1606.     fclose(pDrawFile);
  1607.     icount++;
  1608. }
  1609. #endif // /DEBUG_OUT_REDRAWLIST_ACTIVITY.
  1610.     }
  1611. cleanup:
  1612.     return hxrslt;
  1613. }
  1614. HX_RESULT
  1615. C3GPPTimedTextRenderer::RemoveFromRedrawList(
  1616.         const C3GPPTextContainer* pTextContainer)
  1617. {
  1618. #if defined(DEBUG_OUT_REDRAWLIST_ACTIVITY)
  1619. FILE* pDrawFile = fopen("c:\3gppttInsertIntoRedrawList.txt", icount?"a+":"w");
  1620. if (pDrawFile)
  1621. {
  1622.     fprintf(pDrawFile, "at time %lutremoving %p tbegin=%lutend=%lut"
  1623.         "prevActivityTime=%lutNextActivityTime=%lun",
  1624.         m_ulTimeOfLastTimeSync, pTextContainer, pTextContainer->GetBeginTime(),
  1625.         pTextContainer->GetEndTime(), pTextContainer->GetPrevActivityTime(),
  1626.         pTextContainer->GetNextActivityTime());
  1627.     fclose(pDrawFile);
  1628.     icount++;
  1629. }
  1630. #endif // /DEBUG_OUT_REDRAWLIST_ACTIVITY.
  1631.     HX_RESULT hxrslt = HXR_UNEXPECTED;
  1632.     LISTPOSITION pos = NULL;
  1633.     if (m_pTextContainerRedrawList  &&  pTextContainer)
  1634.     {
  1635.         hxrslt = HXR_OK;
  1636.         // /Find it and remove it if it's in there:
  1637.         pos = m_pTextContainerRedrawList->Find((void*)pTextContainer);
  1638.         if (pos)
  1639.         {
  1640.             m_pTextContainerRedrawList->RemoveAt(pos);
  1641.         }
  1642.     }
  1643.     return hxrslt;
  1644. }
  1645. #if defined(USE_DIB_SECTION) // /                                              -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1646. /****************************************************************************
  1647.  *  IUnknown::AddRef                                            ref:  pncom.h
  1648.  *
  1649.  *  Get new space for bitmapinfo struct (usually plus some bytes for color)
  1650.  */
  1651. BOOL
  1652. C3GPPTimedTextRenderer::AllocNewLPBITMAPINFO(UINT32 ulNumBytes)
  1653. {
  1654.     if (m_LPBITMAPINFO)
  1655.     {    //This SHOULD have been initialized to NULL, so free it:
  1656.         delete m_LPBITMAPINFO;
  1657.         m_LPBITMAPINFO = NULL;
  1658.     }
  1659.     m_LPBITMAPINFO = (LPBITMAPINFO) new BYTE[ulNumBytes];
  1660.     return (NULL != m_LPBITMAPINFO);
  1661. }
  1662. #endif //USE_DIB_SECTION.                                                      _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1663. // IUnknown COM Interface Methods
  1664. /****************************************************************************
  1665.  *  IUnknown::AddRef                                            ref:  pncom.h
  1666.  *
  1667.  *  This routine increases the object reference count in a thread safe
  1668.  *  manner. The reference count is used to manage the lifetime of an object.
  1669.  *  This method must be explicitly called by the user whenever a new
  1670.  *  reference to an object is used.
  1671.  */
  1672. STDMETHODIMP_(UINT32)
  1673. C3GPPTimedTextRenderer::AddRef()
  1674. {
  1675.     return InterlockedIncrement(&m_lRefCount);
  1676. }
  1677. /****************************************************************************
  1678.  *  IUnknown::Release                                           ref:  pncom.h
  1679.  *
  1680.  *  This routine decreases the object reference count in a thread safe
  1681.  *  manner, and deletes the object if no more references to it exist. It must
  1682.  *  be called explicitly by the user whenever an object is no longer needed.
  1683.  */
  1684. STDMETHODIMP_(UINT32)
  1685. C3GPPTimedTextRenderer::Release()
  1686. {
  1687.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1688.     {
  1689.         return m_lRefCount;
  1690.     }
  1691.     delete this;
  1692.     return 0;
  1693. }
  1694. /****************************************************************************
  1695.  *  IUnknown::QueryInterface                                    ref:  pncom.h
  1696.  *
  1697.  *  This routine indicates which interfaces this object supports. If a given
  1698.  *  interface is supported, the object's reference count is incremented, and
  1699.  *  a reference to that interface is returned. Otherwise a NULL object and
  1700.  *  error code are returned. This method is called by other objects to
  1701.  *  discover the functionality of this object.
  1702.  */
  1703. STDMETHODIMP
  1704. C3GPPTimedTextRenderer::QueryInterface(REFIID riid, void** ppvObj)
  1705. {
  1706.     if (IsEqualIID(riid, IID_IUnknown))
  1707.     {
  1708.         AddRef();
  1709.         *ppvObj = (IUnknown*)(IHXPlugin*)this;
  1710.         return HXR_OK;
  1711.     }
  1712.     else if (IsEqualIID(riid, IID_IHXPlugin))
  1713.     {
  1714.         AddRef();
  1715.         *ppvObj = (IHXPlugin*)this;
  1716.         return HXR_OK;
  1717.     }
  1718.     else if (IsEqualIID(riid, IID_IHXRenderer))
  1719.     {
  1720.         AddRef();
  1721.         *ppvObj = (IHXRenderer*)this;
  1722.         return HXR_OK;
  1723.     }
  1724.     else if (IsEqualIID(riid, IID_IHXSiteUser))
  1725.     {
  1726.         AddRef();
  1727.         *ppvObj = (IHXSiteUser*)this;
  1728.         return HXR_OK;
  1729.     }
  1730. #if defined (HELIX_FEATURE_MISU)
  1731.     else if (IsEqualIID(riid, IID_IHXSiteUserSupplier))
  1732.     {
  1733.         if (m_pMISUS)
  1734.         {
  1735.             return m_pMISUS->QueryInterface(IID_IHXSiteUserSupplier,ppvObj);
  1736.         }
  1737.         else
  1738.         {
  1739.             *ppvObj = NULL;
  1740.             return HXR_UNEXPECTED;
  1741.         }
  1742.     }
  1743. #endif // / HELIX_FEATURE_MISU.
  1744.     *ppvObj = NULL;
  1745.     return HXR_NOINTERFACE;
  1746. }
  1747. HX_RESULT
  1748. C3GPPTimedTextRenderer::CreateOffscreenBuffer(HXxSize& hxsize)
  1749. {
  1750.     HX_RESULT retVal = HXR_OK;
  1751.     
  1752. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1753.     // /Create offscreen bitmap.
  1754.     HX_ASSERT(!m_pBitMap);
  1755.     HX_DELETE(m_pBitMap);
  1756.     m_pBitMap = new CFbsBitmap();
  1757.     HX_ASSERT(m_pBitMap);
  1758.     if(!m_pBitMap)
  1759.     {
  1760.         retVal = HXR_OUTOFMEMORY;
  1761.     }
  1762.     else
  1763.     {
  1764.         // /XXXEH- EColor16M (24-bit) means 3 bytes are allocated per pixel.
  1765.         TInt err = m_pBitMap->Create(TSize(hxsize.cx, hxsize.cy),
  1766. #if (12 == HX_3GPPTT_DEFAULT_bits_PER_PIXEL)
  1767.                 EColor4K /*12-bit*/
  1768. #elif (16 == HX_3GPPTT_DEFAULT_bits_PER_PIXEL)
  1769.                 EColor64K /*16-bit*/
  1770. #elif (24 == HX_3GPPTT_DEFAULT_bits_PER_PIXEL)
  1771.                 EColor16M /*24-bit*/
  1772. #else
  1773. #error: cant create CFbsBitmap with color depth > 24
  1774. #endif // /12 , elif 16 , elif 24 == HX_3GPPTT_DEFAULT_bits_PER_PIXEL else...
  1775.                 );
  1776.         HX_ASSERT( err == KErrNone );
  1777.         
  1778.         if( err != KErrNone )
  1779.         {
  1780.             retVal = HXR_OUTOFMEMORY;
  1781.         }
  1782.         else
  1783.         {
  1784.             m_pDrawOutputBuffer = (UCHAR*)m_pBitMap->DataAddress();
  1785.             m_ulDrawOutputBufferSizeInBytes = m_ulBitsPerPixel *
  1786.                     (UINT32)hxsize.cx * (UINT32)hxsize.cy / 8;
  1787.             // /Create the offscreen GC for DrawText() calls:
  1788.             m_pGCOffscreen = NULL;
  1789.             CFbsBitmapDevice* pBsBitmapDevice =
  1790.                     CFbsBitmapDevice::NewL(m_pBitMap);
  1791.             HX_ASSERT(pBsBitmapDevice);
  1792.             if (pBsBitmapDevice)
  1793.             {
  1794.                 err = pBsBitmapDevice->CreateContext(m_pGCOffscreen);
  1795.                 HX_ASSERT(KErrNone == err);
  1796.                 if (KErrNone != err)
  1797.                 {
  1798.                     HX_ASSERT(false);
  1799.                     m_pGCOffscreen = NULL;
  1800.                 }
  1801.             }
  1802.             if (!pBsBitmapDevice  ||  !m_pGCOffscreen)
  1803.             {
  1804.                 retVal = HXR_OUTOFMEMORY;// /XXXEH- can fail for other reasons?
  1805.             }
  1806.         }
  1807.     }
  1808.     HX_ASSERT(retVal==HXR_OK);
  1809.     if( FAILED(retVal) )
  1810.     {
  1811.         HX_DELETE(m_pBitMap);
  1812.         m_pDrawOutputBuffer = NULL;
  1813.         m_ulDrawOutputBufferSizeInBytes = 0;
  1814.     }
  1815. #elif !defined(USE_DIB_SECTION) // /else of _SYMBIAN                           ------------------------------------
  1816.     // / Allocate an output buffer if none yet exists:
  1817.     if (!m_pDrawOutputBuffer  &&  m_size.cx > 0  &&  m_size.cy > 0)
  1818.     {
  1819.         // Compute the size of the output buffer
  1820.         UINT32 ulDataWidth       = (UINT32)m_size.cx * m_ulBitsPerPixel / 8;
  1821.         // /Round up to nearest multiple of 4:
  1822.         UINT32 ulPaddedWidth     = (ulDataWidth + 3) & ~3;
  1823.         m_ulDrawOutputBufferSizeInBytes = ulPaddedWidth * (UINT32)m_size.cy;
  1824.         m_pDrawOutputBuffer      = new BYTE [m_ulDrawOutputBufferSizeInBytes];
  1825.         if (!m_pDrawOutputBuffer)
  1826.         {
  1827.             retVal = HXR_OUTOFMEMORY;
  1828.             goto cleanup;
  1829.         }
  1830.         /* Clear the output buffer */
  1831.         memset(m_pDrawOutputBuffer, 0, m_ulDrawOutputBufferSizeInBytes);
  1832.     }
  1833. #else // /else USE_DIB_SECTION (_WINDOWS): // /                                ------------------------------------
  1834.     if (!m_hBitmap)
  1835.     {
  1836.         HDC hDC = (HDC)m_pDeviceContextMemory;
  1837.         m_BITMAPINFOHEADER.biSize  = sizeof(BITMAPINFOHEADER);
  1838.         m_BITMAPINFOHEADER.biWidth = m_size.cx;
  1839.         m_BITMAPINFOHEADER.biHeight = m_size.cy;
  1840.         m_BITMAPINFOHEADER.biPlanes = 1;  //Must be 1.
  1841.         m_BITMAPINFOHEADER.biBitCount = 32; //Bit depth.
  1842.         m_BITMAPINFOHEADER.biCompression = HX_RGB;
  1843.         m_BITMAPINFOHEADER.biSizeImage =//size of image (bytes):
  1844.                 m_size.cx * m_size.cy *
  1845.                 (m_BITMAPINFOHEADER.biBitCount/8);
  1846.         m_BITMAPINFOHEADER.biClrUsed       = 0;
  1847.         m_BITMAPINFOHEADER.biClrImportant  = 0;
  1848.         m_BITMAPINFOHEADER.biXPelsPerMeter = 0;
  1849.         m_BITMAPINFOHEADER.biYPelsPerMeter = 0;
  1850.         //Allocate space for a BITMAPINFOHEADER and the 3 color masks :
  1851.         if (NULL == m_LPBITMAPINFO)
  1852.         {
  1853.             AllocNewLPBITMAPINFO(sizeof(BITMAPINFOHEADER) +
  1854.                     4 * sizeof(ULONG32));
  1855.             if (!m_LPBITMAPINFO)
  1856.             {
  1857.                 retVal = HXR_OUTOFMEMORY;  //malloc failed.
  1858.                 goto cleanup;
  1859.             }
  1860.             memset(m_LPBITMAPINFO, 0, sizeof(BITMAPINFOHEADER) +
  1861.                     4 * sizeof(ULONG32));
  1862.             ULONG32* colorMasksPtr = //For RGB 888 format:
  1863.                     (ULONG32*)m_LPBITMAPINFO->bmiColors;
  1864.             colorMasksPtr[0] = 0x00ff0000; //8 bits for red.
  1865.             colorMasksPtr[1] = 0x0000ff00; //8 bits for green.
  1866.             colorMasksPtr[2] = 0x000000ff; //8 bits for blue.
  1867.         }
  1868.         //Make sure we're pointing at the new info (using the default
  1869.         // assignment operator since there are no ptrs in
  1870.         // BITMAPINFOHEADER struct):
  1871.         m_LPBITMAPINFO->bmiHeader = m_BITMAPINFOHEADER;
  1872.         m_hBitmap = ::CreateDIBSection(NULL, m_LPBITMAPINFO,
  1873.                 DIB_RGB_COLORS, (void**)&m_pDrawOutputBuffer, NULL, 0);
  1874.         if (!m_hBitmap)
  1875.         {
  1876.             retVal = HXR_OUTOFMEMORY;
  1877.             goto cleanup;
  1878.         }
  1879.         m_ulDrawOutputBufferSizeInBytes = m_BITMAPINFOHEADER.biSizeImage;
  1880.         m_hOldBitmap = (HBITMAP)(::SelectObject(hDC, m_hBitmap));
  1881.         if (!m_hOldBitmap)
  1882.         {
  1883.             retVal = HXR_OUTOFMEMORY;
  1884.             goto cleanup;
  1885.         }
  1886.     }
  1887. #endif // /end if _SYMBIAN elif !USE_DIB_SECTION else (USE_DIB_SECTION)        _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1888. cleanup:
  1889.     return retVal;
  1890. }
  1891. HX_RESULT
  1892. C3GPPTimedTextRenderer::RecomputeTextContainerDrawList(UINT32 ulCurTime)
  1893. {
  1894.     // /Adjust m_pTextContainerListFutureTimePos so that it points
  1895.     // to the text that is current at time ulCurTime:
  1896.     if (m_pTextContainerRedrawList)
  1897.     {
  1898.         // /The text containers inside are owned by (& will be cleaned up by)
  1899.         // the m_pTextContainerList:
  1900.         m_pTextContainerRedrawList->RemoveAll();
  1901.     }
  1902.     // /Helps fix many seeking problems (Helix Issue 667):
  1903.     if (m_pTextContainerList)
  1904.     {
  1905.         C3GPPTextContainer* pTextContainer = NULL;
  1906.         // /Reset draw update times and find the time-current T.C.:
  1907.         LISTPOSITION pos = m_pTextContainerList->GetHeadPosition();
  1908.         while (pos)
  1909.         {
  1910.             m_pTextContainerListFutureTimePos = pos;
  1911.             pTextContainer =
  1912.                     (C3GPPTextContainer*)m_pTextContainerList->GetNext(pos);
  1913.             HX_ASSERT(pTextContainer);
  1914.             pTextContainer->m_ulPrevDrawUpdateTimeOffset = HX_3GPPTT_INVALID_TIME;
  1915.             pTextContainer->m_ulNextDrawUpdateTimeOffset = 0;
  1916.             if (pTextContainer  &&
  1917.                     pTextContainer->GetBeginTime() <= ulCurTime  &&
  1918.                     pTextContainer->GetEndTime()   >  ulCurTime)
  1919.             {
  1920.                 break; // /We found the first time-current one.
  1921.             }
  1922.         }
  1923.         while (pos) // /pos already points to next due to GetNext, above
  1924.         {
  1925.             LISTPOSITION posRemove = pos;
  1926.             pTextContainer =
  1927.                     (C3GPPTextContainer*)m_pTextContainerList->GetNext(pos);
  1928.             HX_ASSERT(pTextContainer);
  1929.             if (pTextContainer)
  1930.             {
  1931.                 if (!m_bGotAllPacketsAlready)
  1932.                 {
  1933.                     // /And now get rid of all later-than-the-seek-to-time
  1934.                     // text since it will be resent by the ff if it's needed:
  1935.                     HX_DELETE(pTextContainer);
  1936.                     m_pTextContainerList->RemoveAt(posRemove);
  1937.                 }
  1938.                 else
  1939.                 {
  1940.                     // /If all packets have arrived then we have all the
  1941.                     // data already and we'll just refuse all future pkts
  1942.                     // in OnPacket() calls so just reset the later-than-
  1943.                     // the-seek-to-time text's draw update variables:
  1944.                     pTextContainer->m_ulPrevDrawUpdateTimeOffset =
  1945.                             HX_3GPPTT_INVALID_TIME;
  1946.                     pTextContainer->m_ulNextDrawUpdateTimeOffset = 0;
  1947.                 }
  1948.             }
  1949.             else
  1950.             {
  1951.                 // /Remove invalid (NULL) T.C. from list:
  1952.                 m_pTextContainerList->RemoveAt(posRemove);
  1953.             }
  1954.         }
  1955.     }
  1956.     return HXR_OK;
  1957. }