Faculty of Information Technology
Software Engineering Group

Ticket #126: issue_126_patch_1_of_1_r93c03926d389.patch

File issue_126_patch_1_of_1_r93c03926d389.patch, 6.5 KB (added by Patrik Svestka, 3 years ago)

Drawing TextOutA and TextOutW chunk-by-chunk

  • WinWorkstation.st

    # HG changeset patch
    # User Patrik Svestka <patrik.svestka@gmail.com>
    # Date 1491301233 -7200
    #      Tue Apr 04 12:20:33 2017 +0200
    # Branch jv
    # Node ID 93c03926d389d69f8e76ee3198b2a3a00ce0ac3e
    # Parent  76834c6940c7f04c6aa22cdd3669b263e64b0fb6
    Issue #126: String text becomes invisible when string length exceeds buffer
    
    Patch fixes an issue, for both TextOutA and TextOutW, where strings longer than 3275 characters fail to draw.
    
    The maximum display buffer is currently at 3275 characters (found by Jan's experiments).  If the string is shorter
    than this buffer than a simple if with SetTextAlign, MoveToEx, and TextOut(A)||(W) is used (no loop).  If the string
    is longer than that there is a while that itterates throught the whole string.  At the end of the string, when it
    is shorter than buffer, (no loop) code is re-used again.
    
    
    
    https://swing.fit.cvut.cz/projects/stx-jv/ticket/126
    
    user: Patrik Svestka <patrik.svestka@gmail.com>
    branch 'jv'
    changed WinWorkstation.st
    
    diff -r 76834c6940c7 -r 93c03926d389 WinWorkstation.st
    a b  
    1076410764%{  /* NOCONTEXT */
    1076510765    unsigned char *cp;
    1076610766    OBJ cls;
    10767     int i1, i2, l, n;
    10768     int nInstBytes;
     10767    long i1, i2, n, l, toDisplay;
     10768    long nInstBytes;
     10769   
    1076910770
    1077010771    if (__isExternalAddress(aGCId)
    1077110772     && __isNonNilObject(aString)
     
    1077310774     && __bothSmallInteger(x, y))
    1077410775    {
    1077510776        struct gcData *gcData;
    10776         int pX, pY;
     10777        long pX, pY;
    1077710778        HDC hDC;
    1077810779        HFONT hOldFont;
    1077910780
     10781  /* Windows (as in 7 or newer) limits the string size for TextOut* to 3275 */
     10782  const int maxDisplayBuffer = 3275;
     10783
    1078010784        i1 = __intVal(index1) - 1;
    1078110785        i2 = __intVal(index2) - 1;
    1078210786        if ((i1 < 0) || (i2 < i1)) {
     
    1081310817#endif
    1081410818
    1081510819        cls = __qClass(aString);
    10816 
    1081710820        cp = __stringVal(aString);
    1081810821        l = i2 - i1 + 1;
    10819         if (l > 32758) {
    10820             /* Windows (as in XP) limits the string size for TextOut* to 32758 */
    10821             l = 32758;
    10822         }
    10823 
    10824         if (__isStringLike(aString)) {
    10825             n = __stringSize(aString);
    10826 commonOutChars:
    10827             if (i2 < n) {
    10828                 cp += i1;
    10829                 CPRINTF(("string1: %s pos=%d/%d l=%d hDC=%x\n", cp, pX, pY,l,hDC));
    10830                 if (! TextOutA(hDC, pX, pY, (char *)cp, l)) {
    10831                     PRINTF(("WinWorkstation [warning]: TextOutA failed. [%d]\n", __LINE__));
    10832                     PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
    10833                     goto error;
    10834                 }
    10835             }
    10836             goto ret;
    10837         }
     10822        toDisplay = l;
     10823
     10824  if (__isStringLike(aString)) {
     10825    n = __stringSize(aString);
     10826    commonOutCharsA:
     10827    if (i2 < n){
     10828      cp += i1;
     10829      if (toDisplay <= maxDisplayBuffer){
     10830        /* set position only during first run */
     10831        if (toDisplay == l){
     10832            SetTextAlign(hDC, TA_UPDATECP);
     10833            MoveToEx(hDC, pX, pY, NULL);
     10834        }
     10835        if (! TextOutA(hDC, 0, 0, (char *)cp, toDisplay)) {
     10836          PRINTF(("WinWorkstation [warning]: TextOutA failed. [%d]\n", __LINE__));
     10837          PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
     10838          goto error;
     10839        }
     10840      }
     10841      else {
     10842        SetTextAlign(hDC, TA_UPDATECP);
     10843        MoveToEx(hDC, pX, pY, NULL);
     10844        /* duplicated to speedup very long strings */
     10845        if (! TextOutA(hDC, 0, 0, (char *)cp, maxDisplayBuffer)) {
     10846            PRINTF(("WinWorkstation [warning]: TextOutA failed. [%d]\n", __LINE__));
     10847            PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
     10848            goto error;
     10849          }
     10850        pX = maxDisplayBuffer;
     10851        cp += maxDisplayBuffer;
     10852        toDisplay -= maxDisplayBuffer;
     10853
     10854        while(toDisplay > maxDisplayBuffer){
     10855          if (! TextOutA(hDC, 0, 0, (char *)cp, maxDisplayBuffer)) {
     10856            PRINTF(("WinWorkstation [warning]: TextOutA failed. [%d]\n", __LINE__));
     10857            PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
     10858            goto error;
     10859          }
     10860          pX += maxDisplayBuffer;
     10861          cp += maxDisplayBuffer;
     10862          toDisplay -= maxDisplayBuffer;
     10863        }
     10864        if (toDisplay > 0){
     10865          goto commonOutCharsA;
     10866        }
     10867      }
     10868    }
     10869    goto ret;
     10870  }
    1083810871
    1083910872        nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
    1084010873        cp += nInstBytes;
    1084110874        n = __byteArraySize(aString) - nInstBytes;
    1084210875
    1084310876        if (__isBytes(aString)) {
    10844             goto commonOutChars;
    10845         }
    10846 
    10847         /* Unicode */
    10848         if (__isWords(aString)) {
    10849             n = n / 2;
    10850             if (i2 < n) {
    10851                 WIDECHAR *w_cp = (WIDECHAR *)cp;
    10852                 w_cp += i1;
    10853                 if (! TextOutW(hDC, pX, pY, w_cp, l)) {
    10854                     PRINTF(("WinWorkstation [warning]: TextOutW failed. [%d]\n", __LINE__));
    10855                     PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
    10856                 }
    10857                 goto ret;
    10858             }
    10859         }
     10877          goto commonOutCharsA;
     10878        }
     10879
     10880  /* Unicode */
     10881  if (__isWords(aString)) {
     10882    n = n / 2;
     10883    WIDECHAR *w_cp = (WIDECHAR *)cp;
     10884    commonOutCharsW:
     10885    if (i2 < n){
     10886      w_cp += i1;
     10887      if (toDisplay <= maxDisplayBuffer){
     10888        /* set position only during first run */
     10889        if (toDisplay == l){
     10890            SetTextAlign(hDC, TA_UPDATECP);
     10891            MoveToEx(hDC, pX, pY, NULL);
     10892        }
     10893        if (! TextOutW(hDC, 0, 0, w_cp, l)) {
     10894          PRINTF(("WinWorkstation [warning]: TextOutW failed. [%d]\n", __LINE__));
     10895          PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
     10896        }
     10897      }
     10898      else {
     10899        SetTextAlign(hDC, TA_UPDATECP);
     10900        MoveToEx(hDC, pX, pY, NULL);
     10901        /* duplicated to speedup very long strings */
     10902        if (! TextOutW(hDC, 0, 0, w_cp, l)) {
     10903          PRINTF(("WinWorkstation [warning]: TextOutW failed. [%d]\n", __LINE__));
     10904          PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
     10905        }
     10906        pX = maxDisplayBuffer;
     10907        w_cp += maxDisplayBuffer;
     10908        toDisplay -= maxDisplayBuffer;
     10909
     10910        while(toDisplay > maxDisplayBuffer){
     10911          if (! TextOutW(hDC, 0, 0, w_cp, l)) {
     10912            PRINTF(("WinWorkstation [warning]: TextOutW failed. [%d]\n", __LINE__));
     10913            PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
     10914          }
     10915          pX += maxDisplayBuffer;
     10916          w_cp += maxDisplayBuffer;
     10917          toDisplay -= maxDisplayBuffer;
     10918        }
     10919        if (toDisplay > 0){
     10920          goto commonOutCharsW;
     10921        }
     10922      }
     10923    }
     10924    goto ret;
     10925  }
    1086010926ret:;
    1086110927#if 0
    1086210928        GcDataReleasePen(hDC, gcData);