⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvdsubber-render.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
字号:
/***********************************************************************
 Copyright 2002 Ben Rudiak-Gould.

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,
 or visit <http://www.gnu.org/copyleft/gpl.html>.
***********************************************************************/


#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include "DVDSubber-compile.h"
#include "DVDSubber-render.h"

#include <stdio.h>


extern ICompilerCallbacks* g_compiler_callbacks;


template<class T>
class List {
   T* head;
public:
   List() { head = 0; }
   void add(T* t) {
      t->next = head;
      head = t;
   }
   T* begin() const {
      return head;
   }
   void split_after(T* t, List<T>* other) {
      other->head = head;
      head = t->next;
      t->next = 0;
   }
   ~List() {
      T* i = begin();
      while (i) {
         T* j = i->next;
         delete i;
         i = j;
      }
   }
};


/********************************************************************
********************************************************************/


int FontInfo::GetTextWidth(wchar_t* text, int textlen) {
   HDC hdc = CreateCompatibleDC(NULL);
   SetMapMode(hdc, MM_TEXT);
   HFONT hfontDefault = (HFONT)SelectObject(hdc, hfont);

   SIZE size;
   if (!GetTextExtentPoint32W(hdc, text, textlen, &size)) {
      throw "GetTextExtentPoint32W failed";
   }

   SelectObject(hdc, hfontDefault);
   DeleteDC(hdc);

   return size.cx;
}

FontInfo::~FontInfo() {
   DeleteObject((HFONT)hfont);
}


/********************************************************************
********************************************************************/


List<FontInfo> saved_fonts;

int largest_height = 1;


int CALLBACK EnumFontsProc(CONST LOGFONT*, CONST TEXTMETRIC*, DWORD, LPARAM pbfound) {
   *(bool*)pbfound = true;
   return 0;
}


FontInfo* LoadFont(const wchar_t* name, int size, bool bold, bool italic) {
   for (FontInfo* i = saved_fonts.begin(); i; i = i->next) {
      if (i->size == size && i->bold == bold && i->italic == italic && wcscmp(i->name, name)==0)
         return i;
   }

   HDC hdc = CreateCompatibleDC(NULL);
   SetMapMode(hdc, MM_TEXT);
//printf("point size %d -> %d\n", size, MulDiv(size, GetDeviceCaps(hdc, LOGPIXELSY), 72));

   HFONT hfont = 0;
   char dbname[256];
   int len = WideCharToMultiByte(CP_ACP, 0, name, -1, dbname, sizeof(dbname), NULL, NULL);
   if (len > 0 && len <= sizeof(dbname)) {
      bool font_exists = false;
      EnumFonts(hdc, dbname, EnumFontsProc, (LPARAM)&font_exists);
      if (!font_exists) {
         char warnbuf[512];
         wsprintf(warnbuf, "A font in this script (%s) is not installed on this system.", dbname);
         g_compiler_callbacks->Warning(warnbuf);
         g_compiler_callbacks->Warning("A different (hopefully similar) font will be substituted.");
      }
      hfont = CreateFont(-size, 0, 0, 0, bold ? FW_BOLD : FW_NORMAL,
         italic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
         CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, dbname);
   }
   if (hfont == 0) {
      throw "CreateFont failed";
   }
   FontInfo* fi = new FontInfo;
   wcscpy(fi->name, name);
   fi->size = size;
   fi->bold = bold;
   fi->italic = italic;
   fi->hfont = hfont;

   HFONT hfontDefault = (HFONT)SelectObject(hdc, fi->hfont);

   TEXTMETRIC tm;
   GetTextMetrics(hdc, &tm);
   fi->height = tm.tmHeight;
   if (tm.tmHeight > largest_height)
      largest_height = tm.tmHeight;
   fi->ascent = tm.tmAscent;
   fi->external_leading = tm.tmExternalLeading;
   static wchar_t space = 32;
   fi->width_of_space = fi->GetTextWidth(&space, 1);
   saved_fonts.add(fi);

   SelectObject(hdc, hfontDefault);
   DeleteDC(hdc);

   return fi;
}


/********************************************************************
********************************************************************/

enum { BMPWIDTH = 800 };

unsigned dib_height = 0;
HBITMAP dib;
unsigned char* dib_bits;
unsigned char* shadow_bits;


void RenderText(
	const wchar_t* text,
	FontInfo* font,
	unsigned char textcolor,
	unsigned char halocolor,
	unsigned char* buf,
	int width, int height,
	int xstride, int ystride,
	int left, int top)
{
   HDC hdc = CreateCompatibleDC(NULL);

   HFONT hfontDefault = (HFONT)SelectObject(hdc, font->hfont);

   if (largest_height + 4 > dib_height) {
      if (dib != 0) {
         DeleteObject(dib);
      }
      delete[] shadow_bits;

      dib_height = largest_height + 4;

      static struct {
         BITMAPINFOHEADER bih;
         RGBQUAD clr[2];
      } b;

      b.bih.biSize          = sizeof(BITMAPINFOHEADER);
      b.bih.biWidth         = BMPWIDTH;
      b.bih.biHeight        = dib_height;
      b.bih.biBitCount      = 1;
      b.bih.biPlanes        = 1;
      b.bih.biCompression   = BI_RGB;
      b.bih.biXPelsPerMeter = 0;
      b.bih.biYPelsPerMeter = 0;
      b.bih.biClrUsed       = 2;
      b.bih.biClrImportant  = 2;
      b.clr[0].rgbBlue = b.clr[0].rgbGreen = b.clr[0].rgbRed = 0;
      b.clr[1].rgbBlue = b.clr[1].rgbGreen = b.clr[1].rgbRed = 255;

      dib = CreateDIBSection(
         hdc,
         (BITMAPINFO *)&b,
         DIB_RGB_COLORS,
         (void**)&dib_bits,
         NULL,
         0);

      shadow_bits = new unsigned char[BMPWIDTH/8 * dib_height];
   }

   memset(dib_bits, 0, BMPWIDTH/8 * dib_height);

   HBITMAP hbmDefault = (HBITMAP)SelectObject(hdc, dib);

   SetMapMode(hdc, MM_TEXT);
   SetTextAlign(hdc, TA_TOP | TA_LEFT /*| TA_RTLREADING*/);
   SetTextColor(hdc, 0xffffff);
   SetBkColor(hdc, 0);

   if (!TextOutW(hdc, (left & 7) + 8, 2, text, lstrlenW(text))) {
      throw "TextOut failed";
   }
   left &= ~7;

   SelectObject(hdc, hbmDefault);
   SelectObject(hdc, hfontDefault);
   DeleteDC(hdc);

   memset(shadow_bits, 0, BMPWIDTH/8 * dib_height);
   for (int q = BMPWIDTH/8 * 2; q < BMPWIDTH/8 * (dib_height - 2); ++q) {
      unsigned char x = dib_bits[q];
      unsigned char x3 = x | (x<<1) | (x>>1);
      unsigned char x5 = x3 | (x3<<1) | (x3>>1);
      unsigned char x3a = x >> 7;
      unsigned char x3b = x << 7;
      unsigned char x5a = (x >> 6) | (x >> 7);
      unsigned char x5b = (x << 6) | (x << 7);
      shadow_bits[q + BMPWIDTH/8 * -2 -1] |= x3a;
      shadow_bits[q + BMPWIDTH/8 * -2   ] |= x3;
      shadow_bits[q + BMPWIDTH/8 * -2 +1] |= x3b;
      shadow_bits[q + BMPWIDTH/8 * -1 -1] |= x5a;
      shadow_bits[q + BMPWIDTH/8 * -1   ] |= x5;
      shadow_bits[q + BMPWIDTH/8 * -1 +1] |= x5b;
      shadow_bits[q + BMPWIDTH/8 *  0 -1] |= x5a;
      shadow_bits[q + BMPWIDTH/8 *  0   ] |= x5;
      shadow_bits[q + BMPWIDTH/8 *  0 +1] |= x5b;
      shadow_bits[q + BMPWIDTH/8 * +1 -1] |= x5a;
      shadow_bits[q + BMPWIDTH/8 * +1   ] |= x5;
      shadow_bits[q + BMPWIDTH/8 * +1 +1] |= x5b;
      shadow_bits[q + BMPWIDTH/8 * +2 -1] |= x3a;
      shadow_bits[q + BMPWIDTH/8 * +2   ] |= x3;
      shadow_bits[q + BMPWIDTH/8 * +2 +1] |= x3b;
   }

   int y_top = dib_height - 1;

   for (int y=0; y<font->height + 4; ++y) {
      int yy = y + top - 2;
      if (yy < 0 || yy >= height) continue;

      for (int x = 0; x < BMPWIDTH/8; ++x) {
         unsigned char textbits = dib_bits[(y_top - y) * BMPWIDTH/8 + x];
         unsigned char halobits = shadow_bits[(y_top - y) * BMPWIDTH/8 + x];
         if ((textbits | halobits) == 0) continue;

         int xx = x*8 + left - 8;
         if (xx < 0 || xx > width-8) continue;

         unsigned char* p = &buf[yy * ystride + xx * xstride];

         for (int bit = 0; bit < 8; ++bit) {
            if (textbits & (128 >> bit)) {
               p[bit * xstride] = textcolor;
            } else if (halobits & (128 >> bit)) {
               p[bit * xstride] = halocolor;
            }
         }
      }
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -