/******************************************************************************** Copyright (C) 2012 Hugh Bailey 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. ********************************************************************************/ #include "Main.h" #include #include #define ClampVal(val, minVal, maxVal) \ if(val < minVal) val = minVal; \ else if(val > maxVal) val = maxVal; #define MAX_TEX_SIZE_W 8192 #define MAX_TEX_SIZE_H 8192 #define MIN_TEX_SIZE_W 32 #define MIN_TEX_SIZE_H 32 inline DWORD GetAlphaVal(UINT opacityLevel) { return ((opacityLevel*255/100)&0xFF) << 24; } class TextOutputSource : public ImageSource { bool bUpdateTexture; String strCurrentText; Texture *texture; float scrollValue; float showExtentTime; int mode; String strText; String strFile; String strFont; int size; DWORD color; UINT opacity; UINT globalOpacity; int scrollSpeed; bool bBold, bItalic, bUnderline, bVertical; UINT backgroundOpacity; DWORD backgroundColor; bool bUseOutline; float outlineSize; DWORD outlineColor; UINT outlineOpacity; bool bUseExtents; UINT extentWidth, extentHeight; bool bWrap; bool bScrollMode; int align; Vect2 baseSize; SIZE textureSize; bool bUsePointFiltering; bool bMonitoringFileChanges; OSFileChangeData *fileChangeMonitor; std::unique_ptr sampler; bool bDoUpdate; SamplerState *ss; XElement *data; void DrawOutlineText(Gdiplus::Graphics *graphics, Gdiplus::Font &font, const Gdiplus::GraphicsPath &path, const Gdiplus::StringFormat &format, const Gdiplus::Brush *brush) { Gdiplus::GraphicsPath *outlinePath; outlinePath = path.Clone(); // Outline color and size UINT tmpOpacity = (UINT)((((float)opacity * 0.01f) * ((float)outlineOpacity * 0.01f)) * 100.0f); Gdiplus::Pen pen(Gdiplus::Color(GetAlphaVal(tmpOpacity) | (outlineColor&0xFFFFFF)), outlineSize); pen.SetLineJoin(Gdiplus::LineJoinRound); // Widen the outline // It seems that Widen has a huge performance impact on DrawPath call, screw it! We're talking about freaking seconds in some extreme cases... //outlinePath->Widen(&pen); // Draw the outline graphics->DrawPath(&pen, outlinePath); // Draw the text graphics->FillPath(brush, &path); delete outlinePath; } HFONT GetFont() { HFONT hFont = NULL; LOGFONT lf; zero(&lf, sizeof(lf)); lf.lfHeight = size; lf.lfWeight = bBold ? FW_BOLD : FW_DONTCARE; lf.lfItalic = bItalic; lf.lfUnderline = bUnderline; lf.lfQuality = ANTIALIASED_QUALITY; if(strFont.IsValid()) { scpy_n(lf.lfFaceName, strFont, 31); hFont = CreateFontIndirect(&lf); } if(!hFont) { scpy_n(lf.lfFaceName, TEXT("Arial"), 31); hFont = CreateFontIndirect(&lf); } return hFont; } void UpdateCurrentText() { if(bMonitoringFileChanges) { OSMonitorFileDestroy(fileChangeMonitor); fileChangeMonitor = NULL; bMonitoringFileChanges = false; } if(mode == 0) strCurrentText = strText; else if(mode == 1 && strFile.IsValid()) { XFile textFile; if(textFile.Open(strFile, XFILE_READ | XFILE_SHARED, XFILE_OPENEXISTING)) { textFile.ReadFileToString(strCurrentText); } else { strCurrentText = TEXT(""); AppWarning(TEXT("TextSource::UpdateTexture: could not open specified file (invalid file name or access violation)")); } if (fileChangeMonitor = OSMonitorFileStart (strFile)) bMonitoringFileChanges = true; } else strCurrentText = TEXT(""); } void SetStringFormat(Gdiplus::StringFormat &format) { UINT formatFlags; formatFlags = Gdiplus::StringFormatFlagsNoFitBlackBox | Gdiplus::StringFormatFlagsMeasureTrailingSpaces; if(bVertical) formatFlags |= Gdiplus::StringFormatFlagsDirectionVertical | Gdiplus::StringFormatFlagsDirectionRightToLeft; format.SetFormatFlags(formatFlags); format.SetTrimming(Gdiplus::StringTrimmingWord); if(bUseExtents && bWrap) switch(align) { case 0: if(bVertical) format.SetLineAlignment(Gdiplus::StringAlignmentFar); else format.SetAlignment(Gdiplus::StringAlignmentNear); break; case 1: if(bVertical) format.SetLineAlignment(Gdiplus::StringAlignmentCenter); else format.SetAlignment(Gdiplus::StringAlignmentCenter); break; case 2: if(bVertical) format.SetLineAlignment(Gdiplus::StringAlignmentNear); else format.SetAlignment(Gdiplus::StringAlignmentFar); break; } else if(bUseExtents && bVertical && !bWrap) format.SetLineAlignment(Gdiplus::StringAlignmentFar); else if(bVertical) format.SetLineAlignment(Gdiplus::StringAlignmentFar); } float ProcessScrollMode(Gdiplus::Graphics *graphics, Gdiplus::Font *font, Gdiplus::RectF &layoutBox, Gdiplus::StringFormat *format) { StringList strList; Gdiplus::RectF boundingBox; float offset = layoutBox.Height; Gdiplus::RectF l2(0.0f ,0.0f , layoutBox.Width, 32000.0f); // Really, it needs to be OVER9000 strCurrentText.FindReplace(L"\n\r", L"\n"); strCurrentText.GetTokenList(strList,'\n'); if(strList.Num() != 0) strCurrentText.Clear(); else return 0.0f; for(int i = strList.Num() - 1; i >= 0; i--) { strCurrentText.InsertString(0, TEXT("\n")); strCurrentText.InsertString(0, strList.GetElement((unsigned int)i).Array()); if(strCurrentText.IsValid()) { graphics->MeasureString(strCurrentText, -1, font, l2, &boundingBox); offset = layoutBox.Height - boundingBox.Height; } if(offset < 0) break; } return offset; } void UpdateTexture() { HFONT hFont; Gdiplus::Status stat; Gdiplus::RectF layoutBox; SIZE textSize; float offset; Gdiplus::RectF boundingBox(0.0f, 0.0f, 32.0f, 32.0f); UpdateCurrentText(); hFont = GetFont(); if(!hFont) return; Gdiplus::StringFormat format(Gdiplus::StringFormat::GenericTypographic()); SetStringFormat(format); HDC hdc = CreateCompatibleDC(NULL); Gdiplus::Font font(hdc, hFont); Gdiplus::Graphics *graphics = new Gdiplus::Graphics(hdc); graphics->SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias); if(strCurrentText.IsValid()) { // Apparently, \0 is not always a zero-width character? // Not including it as part of the string measurement may cut off the final word // on the line when using certain fonts together with outlines and wrapping. INT strLength = strCurrentText.Length() + 1; if(bUseExtents && bWrap) { layoutBox.X = layoutBox.Y = 0; layoutBox.Width = float(extentWidth); layoutBox.Height = float(extentHeight); if(bUseOutline) { //Note: since there's no path widening in DrawOutlineText the padding is half than what it was supposed to be. layoutBox.Width -= outlineSize; layoutBox.Height -= outlineSize; } if(!bVertical && bScrollMode) { offset = ProcessScrollMode(graphics, &font, layoutBox, &format); boundingBox = layoutBox; boundingBox.Y = offset; if(offset < 0) boundingBox.Height -= offset; } else { stat = graphics->MeasureString(strCurrentText, strLength, &font, layoutBox, &format, &boundingBox); if(stat != Gdiplus::Ok) AppWarning(TEXT("TextSource::UpdateTexture: Gdiplus::Graphics::MeasureString failed: %u"), (int)stat); } } else { stat = graphics->MeasureString(strCurrentText, strLength, &font, Gdiplus::PointF(0.0f, 0.0f), &format, &boundingBox); if(stat != Gdiplus::Ok) AppWarning(TEXT("TextSource::UpdateTexture: Gdiplus::Graphics::MeasureString failed: %u"), (int)stat); if(bUseOutline) { //Note: since there's no path widening in DrawOutlineText the padding is half than what it was supposed to be. boundingBox.Width += outlineSize; boundingBox.Height += outlineSize; } } } delete graphics; DeleteDC(hdc); hdc = NULL; DeleteObject(hFont); if(bVertical) { if(boundingBox.Width textSize.cx) textSize.cx = extentWidth; if(LONG(extentHeight) > textSize.cy) textSize.cy = extentHeight; } } //textSize.cx &= 0xFFFFFFFE; //textSize.cy &= 0xFFFFFFFE; textSize.cx += textSize.cx%2; textSize.cy += textSize.cy%2; ClampVal(textSize.cx, MIN_TEX_SIZE_W, MAX_TEX_SIZE_W); ClampVal(textSize.cy, MIN_TEX_SIZE_H, MAX_TEX_SIZE_H); //---------------------------------------------------------------------- // write image { HDC hTempDC = CreateCompatibleDC(NULL); BITMAPINFO bi; zero(&bi, sizeof(bi)); void* lpBits; BITMAPINFOHEADER &bih = bi.bmiHeader; bih.biSize = sizeof(bih); bih.biBitCount = 32; bih.biWidth = textSize.cx; bih.biHeight = textSize.cy; bih.biPlanes = 1; HBITMAP hBitmap = CreateDIBSection(hTempDC, &bi, DIB_RGB_COLORS, &lpBits, NULL, 0); Gdiplus::Bitmap bmp(textSize.cx, textSize.cy, 4*textSize.cx, PixelFormat32bppARGB, (BYTE*)lpBits); graphics = new Gdiplus::Graphics(&bmp); Gdiplus::SolidBrush *brush = new Gdiplus::SolidBrush(Gdiplus::Color(GetAlphaVal(opacity)|(color&0x00FFFFFF))); DWORD bkColor; if(backgroundOpacity == 0 && scrollSpeed !=0) bkColor = 1<<24 | (color&0x00FFFFFF); else bkColor = ((strCurrentText.IsValid() || bUseExtents) ? GetAlphaVal(backgroundOpacity) : GetAlphaVal(0)) | (backgroundColor&0x00FFFFFF); if((textSize.cx > boundingBox.Width || textSize.cy > boundingBox.Height) && !bUseExtents) { stat = graphics->Clear(Gdiplus::Color( 0x00000000)); if(stat != Gdiplus::Ok) AppWarning(TEXT("TextSource::UpdateTexture: Graphics::Clear failed: %u"), (int)stat); Gdiplus::SolidBrush *bkBrush = new Gdiplus::SolidBrush(Gdiplus::Color( bkColor )); graphics->FillRectangle(bkBrush, boundingBox); delete bkBrush; } else { stat = graphics->Clear(Gdiplus::Color( bkColor )); if(stat != Gdiplus::Ok) AppWarning(TEXT("TextSource::UpdateTexture: Graphics::Clear failed: %u"), (int)stat); } graphics->SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias); graphics->SetCompositingMode(Gdiplus::CompositingModeSourceOver); graphics->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); if(strCurrentText.IsValid()) { if(bUseOutline) { boundingBox.Offset(outlineSize/2, outlineSize/2); Gdiplus::FontFamily fontFamily; Gdiplus::GraphicsPath path; font.GetFamily(&fontFamily); path.AddString(strCurrentText, -1, &fontFamily, font.GetStyle(), font.GetSize(), boundingBox, &format); DrawOutlineText(graphics, font, path, format, brush); } else { stat = graphics->DrawString(strCurrentText, -1, &font, boundingBox, &format, brush); if(stat != Gdiplus::Ok) AppWarning(TEXT("TextSource::UpdateTexture: Graphics::DrawString failed: %u"), (int)stat); } } delete brush; delete graphics; //---------------------------------------------------------------------- // upload texture if(textureSize.cx != textSize.cx || textureSize.cy != textSize.cy) { if(texture) { delete texture; texture = NULL; } mcpy(&textureSize, &textSize, sizeof(textureSize)); texture = CreateTexture(textSize.cx, textSize.cy, GS_BGRA, lpBits, FALSE, FALSE); } else if(texture) texture->SetImage(lpBits, GS_IMAGEFORMAT_BGRA, 4*textSize.cx); if(!texture) { AppWarning(TEXT("TextSource::UpdateTexture: could not create texture")); DeleteObject(hFont); } DeleteDC(hTempDC); DeleteObject(hBitmap); } } public: inline TextOutputSource(XElement *data) { this->data = data; UpdateSettings(); SamplerInfo si; zero(&si, sizeof(si)); si.addressU = GS_ADDRESS_REPEAT; si.addressV = GS_ADDRESS_REPEAT; si.borderColor = 0; si.filter = GS_FILTER_LINEAR; ss = CreateSamplerState(si); globalOpacity = 100; Log(TEXT("Using text output")); } ~TextOutputSource() { if(texture) { delete texture; texture = NULL; } delete ss; if(bMonitoringFileChanges) { OSMonitorFileDestroy(fileChangeMonitor); } } void Preprocess() { if(bMonitoringFileChanges) { if (OSFileHasChanged(fileChangeMonitor)) bUpdateTexture = true; } if(bUpdateTexture) { bUpdateTexture = false; UpdateTexture(); } } void Tick(float fSeconds) { if(scrollSpeed != 0 && texture) { scrollValue += fSeconds*float(scrollSpeed)/(bVertical?(-1.0f)*float(textureSize.cy):float(textureSize.cx)); while(scrollValue > 1.0f) scrollValue -= 1.0f; while(scrollValue < -1.0f) scrollValue += 1.0f; } if(showExtentTime > 0.0f) showExtentTime -= fSeconds; if(bDoUpdate) { bDoUpdate = false; bUpdateTexture = true; } } void Render(const Vect2 &pos, const Vect2 &size) { if(texture) { //EnableBlending(FALSE); Vect2 sizeMultiplier = size/baseSize; Vect2 newSize = Vect2(float(textureSize.cx), float(textureSize.cy))*sizeMultiplier; if(bUseExtents) { Vect2 extentVal = Vect2(float(extentWidth), float(extentHeight))*sizeMultiplier; if(showExtentTime > 0.0f) { Shader *pShader = GS->GetCurrentPixelShader(); Shader *vShader = GS->GetCurrentVertexShader(); Color4 rectangleColor = Color4(0.0f, 1.0f, 0.0f, 1.0f); if(showExtentTime < 1.0f) rectangleColor.w = showExtentTime; App->solidPixelShader->SetColor(App->solidPixelShader->GetParameter(0), rectangleColor); LoadVertexShader(App->solidVertexShader); LoadPixelShader(App->solidPixelShader); DrawBox(pos, extentVal); LoadVertexShader(vShader); LoadPixelShader(pShader); } if(!bWrap) { XRect rect = {int(pos.x), int(pos.y), int(extentVal.x), int(extentVal.y)}; SetScissorRect(&rect); } } if(bUsePointFiltering) { if (!sampler) { SamplerInfo samplerinfo; samplerinfo.filter = GS_FILTER_POINT; std::unique_ptr new_sampler(CreateSamplerState(samplerinfo)); sampler = std::move(new_sampler); } LoadSamplerState(sampler.get(), 0); } DWORD alpha = DWORD(double(globalOpacity)*2.55); DWORD outputColor = (alpha << 24) | 0xFFFFFF; if(scrollSpeed != 0) { UVCoord ul(0.0f, 0.0f); UVCoord lr(1.0f, 1.0f); if(bVertical) { /*float sizeVal = float(textureSize.cy); float clampedVal = floorf(scrollValue*sizeVal)/sizeVal;*/ ul.y += scrollValue; lr.y += scrollValue; } else { /*float sizeVal = float(textureSize.cx); float clampedVal = floorf(scrollValue*sizeVal)/sizeVal;*/ ul.x += scrollValue; lr.x += scrollValue; } LoadSamplerState(ss); DrawSpriteEx(texture, outputColor, pos.x, pos.y, pos.x+newSize.x, pos.y+newSize.y, ul.x, ul.y, lr.x, lr.y); } else DrawSprite(texture, outputColor, pos.x, pos.y, pos.x+newSize.x, pos.y+newSize.y); if (bUsePointFiltering) LoadSamplerState(NULL, 0); if(bUseExtents && !bWrap) SetScissorRect(NULL); //EnableBlending(TRUE); } } Vect2 GetSize() const { return baseSize; } void UpdateSettings() { strFont = data->GetString(TEXT("font"), TEXT("Arial")); color = data->GetInt(TEXT("color"), 0xFFFFFFFF); size = data->GetInt(TEXT("fontSize"), 48); opacity = data->GetInt(TEXT("textOpacity"), 100); scrollSpeed = data->GetInt(TEXT("scrollSpeed"), 0); bBold = data->GetInt(TEXT("bold"), 0) != 0; bItalic = data->GetInt(TEXT("italic"), 0) != 0; bWrap = data->GetInt(TEXT("wrap"), 0) != 0; bScrollMode = data->GetInt(TEXT("scrollMode"), 0) != 0; bUnderline = data->GetInt(TEXT("underline"), 0) != 0; bVertical = data->GetInt(TEXT("vertical"), 0) != 0; bUseExtents = data->GetInt(TEXT("useTextExtents"), 0) != 0; extentWidth = data->GetInt(TEXT("extentWidth"), 0); extentHeight= data->GetInt(TEXT("extentHeight"), 0); align = data->GetInt(TEXT("align"), 0); strFile = data->GetString(TEXT("file")); strText = data->GetString(TEXT("text")); mode = data->GetInt(TEXT("mode"), 0); bUsePointFiltering = data->GetInt(TEXT("pointFiltering"), 0) != 0; baseSize.x = data->GetFloat(TEXT("baseSizeCX"), MIN_TEX_SIZE_W); baseSize.y = data->GetFloat(TEXT("baseSizeCY"), MIN_TEX_SIZE_H); bUseOutline = data->GetInt(TEXT("useOutline")) != 0; outlineColor = data->GetInt(TEXT("outlineColor"), 0xFF000000); outlineSize = data->GetFloat(TEXT("outlineSize"), 2); outlineOpacity = data->GetInt(TEXT("outlineOpacity"), 100); backgroundColor = data->GetInt(TEXT("backgroundColor"), 0xFF000000); backgroundOpacity = data->GetInt(TEXT("backgroundOpacity"), 0); bUpdateTexture = true; } void SetString(CTSTR lpName, CTSTR lpVal) { if(scmpi(lpName, TEXT("font")) == 0) strFont = lpVal; else if(scmpi(lpName, TEXT("text")) == 0) strText = lpVal; else if(scmpi(lpName, TEXT("file")) == 0) strFile = lpVal; bUpdateTexture = true; } void SetInt(CTSTR lpName, int iValue) { if(scmpi(lpName, TEXT("color")) == 0) color = iValue; else if(scmpi(lpName, TEXT("fontSize")) == 0) size = iValue; else if(scmpi(lpName, TEXT("textOpacity")) == 0) opacity = iValue; else if(scmpi(lpName, TEXT("scrollSpeed")) == 0) { if(scrollSpeed == 0) scrollValue = 0.0f; scrollSpeed = iValue; } else if(scmpi(lpName, TEXT("bold")) == 0) bBold = iValue != 0; else if(scmpi(lpName, TEXT("italic")) == 0) bItalic = iValue != 0; else if(scmpi(lpName, TEXT("wrap")) == 0) bWrap = iValue != 0; else if(scmpi(lpName, TEXT("scrollMode")) == 0) bScrollMode = iValue != 0; else if(scmpi(lpName, TEXT("underline")) == 0) bUnderline = iValue != 0; else if(scmpi(lpName, TEXT("vertical")) == 0) bVertical = iValue != 0; else if(scmpi(lpName, TEXT("useTextExtents")) == 0) bUseExtents = iValue != 0; else if(scmpi(lpName, TEXT("extentWidth")) == 0) { showExtentTime = 2.0f; extentWidth = iValue; } else if(scmpi(lpName, TEXT("extentHeight")) == 0) { showExtentTime = 2.0f; extentHeight = iValue; } else if(scmpi(lpName, TEXT("align")) == 0) align = iValue; else if(scmpi(lpName, TEXT("mode")) == 0) mode = iValue; else if(scmpi(lpName, TEXT("useOutline")) == 0) bUseOutline = iValue != 0; else if(scmpi(lpName, TEXT("outlineColor")) == 0) outlineColor = iValue; else if(scmpi(lpName, TEXT("outlineOpacity")) == 0) outlineOpacity = iValue; else if(scmpi(lpName, TEXT("backgroundColor")) == 0) backgroundColor = iValue; else if(scmpi(lpName, TEXT("backgroundOpacity")) == 0) backgroundOpacity = iValue; bUpdateTexture = true; } void SetFloat(CTSTR lpName, float fValue) { if(scmpi(lpName, TEXT("outlineSize")) == 0) outlineSize = fValue; bUpdateTexture = true; } inline void ResetExtentRect() {showExtentTime = 0.0f;} }; struct ConfigTextSourceInfo { CTSTR lpName; XElement *data; float cx, cy; StringList fontNames; StringList fontFaces; }; ImageSource* STDCALL CreateTextSource(XElement *data) { if(!data) return NULL; return new TextOutputSource(data); } int CALLBACK FontEnumProcThingy(ENUMLOGFONTEX *logicalData, NEWTEXTMETRICEX *physicalData, DWORD fontType, ConfigTextSourceInfo *configInfo) { if(fontType == TRUETYPE_FONTTYPE) //HomeWorld - GDI+ doesn't like anything other than truetype { configInfo->fontNames << logicalData->elfFullName; configInfo->fontFaces << logicalData->elfLogFont.lfFaceName; } return 1; } void DoCancelStuff(HWND hwnd) { ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); ImageSource *source = API->GetSceneImageSource(configInfo->lpName); //XElement *data = configInfo->data; if(source) source->UpdateSettings(); } UINT FindFontFace(ConfigTextSourceInfo *configInfo, HWND hwndFontList, CTSTR lpFontFace) { UINT id = configInfo->fontFaces.FindValueIndexI(lpFontFace); if(id == INVALID) return INVALID; else { for(UINT i=0; ifontFaces.Num(); i++) { UINT targetID = (UINT)SendMessage(hwndFontList, CB_GETITEMDATA, i, 0); if(targetID == id) return i; } } return INVALID; } UINT FindFontName(ConfigTextSourceInfo *configInfo, HWND hwndFontList, CTSTR lpFontFace) { return configInfo->fontNames.FindValueIndexI(lpFontFace); } CTSTR GetFontFace(ConfigTextSourceInfo *configInfo, HWND hwndFontList) { UINT id = (UINT)SendMessage(hwndFontList, CB_GETCURSEL, 0, 0); if(id == CB_ERR) return NULL; UINT actualID = (UINT)SendMessage(hwndFontList, CB_GETITEMDATA, id, 0); return configInfo->fontFaces[actualID]; } INT_PTR CALLBACK ConfigureTextProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static bool bInitializedDialog = false; switch(message) { case WM_INITDIALOG: { ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)lParam; SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)configInfo); LocalizeWindow(hwnd); XElement *data = configInfo->data; //----------------------------------------- HDC hDCtest = GetDC(hwnd); LOGFONT lf; zero(&lf, sizeof(lf)); EnumFontFamiliesEx(hDCtest, &lf, (FONTENUMPROC)FontEnumProcThingy, (LPARAM)configInfo, 0); HWND hwndFonts = GetDlgItem(hwnd, IDC_FONT); for(UINT i=0; ifontNames.Num(); i++) { int id = (int)SendMessage(hwndFonts, CB_ADDSTRING, 0, (LPARAM)configInfo->fontNames[i].Array()); SendMessage(hwndFonts, CB_SETITEMDATA, id, (LPARAM)i); } CTSTR lpFont = data->GetString(TEXT("font")); UINT id = FindFontFace(configInfo, hwndFonts, lpFont); if(id == INVALID) id = (UINT)SendMessage(hwndFonts, CB_FINDSTRINGEXACT, -1, (LPARAM)TEXT("Arial")); SendMessage(hwndFonts, CB_SETCURSEL, id, 0); //----------------------------------------- SendMessage(GetDlgItem(hwnd, IDC_TEXTSIZE), UDM_SETRANGE32, 5, MAX_TEX_SIZE_H); SendMessage(GetDlgItem(hwnd, IDC_TEXTSIZE), UDM_SETPOS32, 0, data->GetInt(TEXT("fontSize"), 48)); //----------------------------------------- CCSetColor(GetDlgItem(hwnd, IDC_COLOR), data->GetInt(TEXT("color"), 0xFFFFFFFF)); SendMessage(GetDlgItem(hwnd, IDC_TEXTOPACITY), UDM_SETRANGE32, 0, 100); SendMessage(GetDlgItem(hwnd, IDC_TEXTOPACITY), UDM_SETPOS32, 0, data->GetInt(TEXT("textOpacity"), 100)); SendMessage(GetDlgItem(hwnd, IDC_SCROLLSPEED), UDM_SETRANGE32, -4095, 4095); SendMessage(GetDlgItem(hwnd, IDC_SCROLLSPEED), UDM_SETPOS32, 0, data->GetInt(TEXT("scrollSpeed"), 0)); SendMessage(GetDlgItem(hwnd, IDC_BOLD), BM_SETCHECK, data->GetInt(TEXT("bold"), 0) ? BST_CHECKED : BST_UNCHECKED, 0); SendMessage(GetDlgItem(hwnd, IDC_ITALIC), BM_SETCHECK, data->GetInt(TEXT("italic"), 0) ? BST_CHECKED : BST_UNCHECKED, 0); SendMessage(GetDlgItem(hwnd, IDC_UNDERLINE), BM_SETCHECK, data->GetInt(TEXT("underline"), 0) ? BST_CHECKED : BST_UNCHECKED, 0); SendMessage(GetDlgItem(hwnd, IDC_VERTICALSCRIPT), BM_SETCHECK, data->GetInt(TEXT("vertical"), 0) ? BST_CHECKED : BST_UNCHECKED, 0); BOOL bUsePointFilter = data->GetInt(TEXT("pointFiltering"), 0) != 0; SendMessage(GetDlgItem(hwnd, IDC_POINTFILTERING), BM_SETCHECK, bUsePointFilter ? BST_CHECKED : BST_UNCHECKED, 0); //----------------------------------------- CCSetColor(GetDlgItem(hwnd, IDC_BACKGROUNDCOLOR), data->GetInt(TEXT("backgroundColor"), 0xFF000000)); SendMessage(GetDlgItem(hwnd, IDC_BACKGROUNDOPACITY), UDM_SETRANGE32, 0, 100); SendMessage(GetDlgItem(hwnd, IDC_BACKGROUNDOPACITY), UDM_SETPOS32, 0, data->GetInt(TEXT("backgroundOpacity"), 0)); //----------------------------------------- bool bChecked = data->GetInt(TEXT("useOutline"), 0) != 0; SendMessage(GetDlgItem(hwnd, IDC_USEOUTLINE), BM_SETCHECK, bChecked ? BST_CHECKED : BST_UNCHECKED, 0); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINETHICKNESS_EDIT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINETHICKNESS), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINECOLOR), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINEOPACITY_EDIT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINEOPACITY), bChecked); SendMessage(GetDlgItem(hwnd, IDC_OUTLINETHICKNESS), UDM_SETRANGE32, 1, 20); SendMessage(GetDlgItem(hwnd, IDC_OUTLINETHICKNESS), UDM_SETPOS32, 0, data->GetInt(TEXT("outlineSize"), 2)); CCSetColor(GetDlgItem(hwnd, IDC_OUTLINECOLOR), data->GetInt(TEXT("outlineColor"), 0xFF000000)); SendMessage(GetDlgItem(hwnd, IDC_OUTLINEOPACITY), UDM_SETRANGE32, 0, 100); SendMessage(GetDlgItem(hwnd, IDC_OUTLINEOPACITY), UDM_SETPOS32, 0, data->GetInt(TEXT("outlineOpacity"), 100)); //----------------------------------------- bChecked = data->GetInt(TEXT("useTextExtents"), 0) != 0; SendMessage(GetDlgItem(hwnd, IDC_USETEXTEXTENTS), BM_SETCHECK, bChecked ? BST_CHECKED : BST_UNCHECKED, 0); ConfigureTextProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_USETEXTEXTENTS, BN_CLICKED), (LPARAM)GetDlgItem(hwnd, IDC_USETEXTEXTENTS)); EnableWindow(GetDlgItem(hwnd, IDC_EXTENTWIDTH_EDIT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_EXTENTHEIGHT_EDIT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_EXTENTWIDTH), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_EXTENTHEIGHT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_WRAP), bChecked); bool bVertical = data->GetInt(TEXT("vertical"), 0) != 0; SendMessage(GetDlgItem(hwnd, IDC_EXTENTWIDTH), UDM_SETRANGE32, MIN_TEX_SIZE_W, MAX_TEX_SIZE_W); SendMessage(GetDlgItem(hwnd, IDC_EXTENTHEIGHT), UDM_SETRANGE32, MIN_TEX_SIZE_H, MAX_TEX_SIZE_H); SendMessage(GetDlgItem(hwnd, IDC_EXTENTWIDTH), UDM_SETPOS32, 0, data->GetInt(TEXT("extentWidth"), MIN_TEX_SIZE_W)); SendMessage(GetDlgItem(hwnd, IDC_EXTENTHEIGHT), UDM_SETPOS32, 0, data->GetInt(TEXT("extentHeight"), MIN_TEX_SIZE_H)); bool bWrap = data->GetInt(TEXT("wrap"), 0) != 0; SendMessage(GetDlgItem(hwnd, IDC_WRAP), BM_SETCHECK, bWrap ? BST_CHECKED : BST_UNCHECKED, 0); bool bScrollMode = data->GetInt(TEXT("scrollMode"), 0) != 0; SendMessage(GetDlgItem(hwnd, IDC_SCROLLMODE), BM_SETCHECK, bScrollMode ? BST_CHECKED : BST_UNCHECKED, 0); EnableWindow(GetDlgItem(hwnd, IDC_ALIGN), bChecked && bWrap); EnableWindow(GetDlgItem(hwnd, IDC_SCROLLMODE), bChecked && bWrap && !bVertical); HWND hwndAlign = GetDlgItem(hwnd, IDC_ALIGN); SendMessage(hwndAlign, CB_ADDSTRING, 0, (LPARAM)Str("Sources.TextSource.Left")); SendMessage(hwndAlign, CB_ADDSTRING, 0, (LPARAM)Str("Sources.TextSource.Center")); SendMessage(hwndAlign, CB_ADDSTRING, 0, (LPARAM)Str("Sources.TextSource.Right")); int align = data->GetInt(TEXT("align"), 0); ClampVal(align, 0, 2); SendMessage(hwndAlign, CB_SETCURSEL, align, 0); //----------------------------------------- BOOL bUseFile = data->GetInt(TEXT("mode"), 0) == 1; SendMessage(GetDlgItem(hwnd, IDC_USEFILE), BM_SETCHECK, bUseFile ? BST_CHECKED : BST_UNCHECKED, 0); SendMessage(GetDlgItem(hwnd, IDC_USETEXT), BM_SETCHECK, bUseFile ? BST_UNCHECKED : BST_CHECKED, 0); SetWindowText(GetDlgItem(hwnd, IDC_TEXT), data->GetString(TEXT("text"))); SetWindowText(GetDlgItem(hwnd, IDC_FILE), data->GetString(TEXT("file"))); EnableWindow(GetDlgItem(hwnd, IDC_TEXT), !bUseFile); EnableWindow(GetDlgItem(hwnd, IDC_FILE), bUseFile); EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), bUseFile); bInitializedDialog = true; return TRUE; } case WM_DESTROY: bInitializedDialog = false; break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_FONT: if(bInitializedDialog) { if(HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_EDITCHANGE) { ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); if(!configInfo) break; String strFont; if(HIWORD(wParam) == CBN_SELCHANGE) strFont = GetFontFace(configInfo, (HWND)lParam); else { UINT id = FindFontName(configInfo, (HWND)lParam, GetEditText((HWND)lParam)); if(id != INVALID) strFont = configInfo->fontFaces[id]; } ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source && strFont.IsValid()) source->SetString(TEXT("font"), strFont); } } break; case IDC_OUTLINECOLOR: case IDC_BACKGROUNDCOLOR: case IDC_COLOR: if(bInitializedDialog) { DWORD color = CCGetColor((HWND)lParam); ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); if(!configInfo) break; ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source) { switch(LOWORD(wParam)) { case IDC_OUTLINECOLOR: source->SetInt(TEXT("outlineColor"), color); break; case IDC_BACKGROUNDCOLOR: source->SetInt(TEXT("backgroundColor"), color); break; case IDC_COLOR: source->SetInt(TEXT("color"), color); break; } } } break; case IDC_TEXTSIZE_EDIT: case IDC_EXTENTWIDTH_EDIT: case IDC_EXTENTHEIGHT_EDIT: case IDC_BACKGROUNDOPACITY_EDIT: case IDC_TEXTOPACITY_EDIT: case IDC_OUTLINEOPACITY_EDIT: case IDC_OUTLINETHICKNESS_EDIT: case IDC_SCROLLSPEED_EDIT: if(HIWORD(wParam) == EN_CHANGE && bInitializedDialog) { int val = (int)SendMessage(GetWindow((HWND)lParam, GW_HWNDNEXT), UDM_GETPOS32, 0, 0); ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); if(!configInfo) break; ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source) { switch(LOWORD(wParam)) { case IDC_TEXTSIZE_EDIT: source->SetInt(TEXT("fontSize"), val); break; case IDC_EXTENTWIDTH_EDIT: source->SetInt(TEXT("extentWidth"), val); break; case IDC_EXTENTHEIGHT_EDIT: source->SetInt(TEXT("extentHeight"), val); break; case IDC_TEXTOPACITY_EDIT: source->SetInt(TEXT("textOpacity"), val); break; case IDC_OUTLINEOPACITY_EDIT: source->SetInt(TEXT("outlineOpacity"), val); break; case IDC_BACKGROUNDOPACITY_EDIT: source->SetInt(TEXT("backgroundOpacity"), val); break; case IDC_OUTLINETHICKNESS_EDIT: source->SetFloat(TEXT("outlineSize"), (float)val); break; case IDC_SCROLLSPEED_EDIT: source->SetInt(TEXT("scrollSpeed"), val); break; } } } break; case IDC_BOLD: case IDC_ITALIC: case IDC_UNDERLINE: case IDC_VERTICALSCRIPT: case IDC_WRAP: case IDC_SCROLLMODE: case IDC_USEOUTLINE: case IDC_USETEXTEXTENTS: if(HIWORD(wParam) == BN_CLICKED && bInitializedDialog) { BOOL bChecked = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED; ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); if(!configInfo) break; ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source) { switch(LOWORD(wParam)) { case IDC_BOLD: source->SetInt(TEXT("bold"), bChecked); break; case IDC_ITALIC: source->SetInt(TEXT("italic"), bChecked); break; case IDC_UNDERLINE: source->SetInt(TEXT("underline"), bChecked); break; case IDC_VERTICALSCRIPT: source->SetInt(TEXT("vertical"), bChecked); break; case IDC_WRAP: source->SetInt(TEXT("wrap"), bChecked); break; case IDC_SCROLLMODE: source->SetInt(TEXT("scrollMode"), bChecked); break; case IDC_USEOUTLINE: source->SetInt(TEXT("useOutline"), bChecked); break; case IDC_USETEXTEXTENTS: source->SetInt(TEXT("useTextExtents"), bChecked); break; } } if(LOWORD(wParam) == IDC_VERTICALSCRIPT) { bool bWrap = SendMessage(GetDlgItem(hwnd, IDC_WRAP), BM_GETCHECK, 0, 0) == BST_CHECKED; bool bUseExtents = SendMessage(GetDlgItem(hwnd, IDC_USETEXTEXTENTS), BM_GETCHECK, 0, 0) == BST_CHECKED; EnableWindow(GetDlgItem(hwnd, IDC_SCROLLMODE), bWrap && bUseExtents && !bChecked); } else if(LOWORD(wParam) == IDC_WRAP) { bool bVertical = SendMessage(GetDlgItem(hwnd, IDC_VERTICALSCRIPT), BM_GETCHECK, 0, 0) == BST_CHECKED; EnableWindow(GetDlgItem(hwnd, IDC_ALIGN), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_SCROLLMODE), bChecked && !bVertical); } else if(LOWORD(wParam) == IDC_USETEXTEXTENTS) { EnableWindow(GetDlgItem(hwnd, IDC_EXTENTWIDTH_EDIT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_EXTENTHEIGHT_EDIT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_EXTENTWIDTH), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_EXTENTHEIGHT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_WRAP), bChecked); bool bWrap = SendMessage(GetDlgItem(hwnd, IDC_WRAP), BM_GETCHECK, 0, 0) == BST_CHECKED; bool bVertical = SendMessage(GetDlgItem(hwnd, IDC_VERTICALSCRIPT), BM_GETCHECK, 0, 0) == BST_CHECKED; EnableWindow(GetDlgItem(hwnd, IDC_ALIGN), bChecked && bWrap); EnableWindow(GetDlgItem(hwnd, IDC_SCROLLMODE), bChecked && bWrap && !bVertical); } else if(LOWORD(wParam) == IDC_USEOUTLINE) { EnableWindow(GetDlgItem(hwnd, IDC_OUTLINETHICKNESS_EDIT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINETHICKNESS), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINECOLOR), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINEOPACITY_EDIT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_OUTLINEOPACITY), bChecked); } } break; case IDC_ALIGN: if(HIWORD(wParam) == CBN_SELCHANGE && bInitializedDialog) { int align = (int)SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); if(align == CB_ERR) break; ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); if(!configInfo) break; ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source) source->SetInt(TEXT("align"), align); } break; case IDC_FILE: case IDC_TEXT: if(HIWORD(wParam) == EN_CHANGE && bInitializedDialog) { String strText = GetEditText((HWND)lParam); ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); if(!configInfo) break; ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source) { switch(LOWORD(wParam)) { case IDC_FILE: source->SetString(TEXT("file"), strText); break; case IDC_TEXT: source->SetString(TEXT("text"), strText); break; } } } break; case IDC_USEFILE: if(HIWORD(wParam) == BN_CLICKED && bInitializedDialog) { EnableWindow(GetDlgItem(hwnd, IDC_TEXT), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_FILE), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), TRUE); ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source) source->SetInt(TEXT("mode"), 1); } break; case IDC_USETEXT: if(HIWORD(wParam) == BN_CLICKED && bInitializedDialog) { EnableWindow(GetDlgItem(hwnd, IDC_TEXT), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_FILE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), FALSE); ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); if(!configInfo) break; ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source) source->SetInt(TEXT("mode"), 0); } break; case IDC_BROWSE: { TCHAR lpFile[MAX_PATH+1]; zero(lpFile, sizeof(lpFile)); OPENFILENAME ofn; zero(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.lpstrFile = lpFile; ofn.hwndOwner = hwnd; ofn.nMaxFile = MAX_PATH; ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0"); ofn.nFilterIndex = 1; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; TCHAR curDirectory[MAX_PATH+1]; GetCurrentDirectory(MAX_PATH, curDirectory); BOOL bOpenFile = GetOpenFileName(&ofn); SetCurrentDirectory(curDirectory); if(bOpenFile) { SetWindowText(GetDlgItem(hwnd, IDC_FILE), lpFile); ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); ImageSource *source = API->GetSceneImageSource(configInfo->lpName); if(source) source->SetString(TEXT("file"), lpFile); } } break; case IDOK: { ConfigTextSourceInfo *configInfo = (ConfigTextSourceInfo*)GetWindowLongPtr(hwnd, DWLP_USER); if(!configInfo) break; XElement *data = configInfo->data; BOOL bUseTextExtents = SendMessage(GetDlgItem(hwnd, IDC_USETEXTEXTENTS), BM_GETCHECK, 0, 0) == BST_CHECKED; BOOL bUseOutline = SendMessage(GetDlgItem(hwnd, IDC_USEOUTLINE), BM_GETCHECK, 0, 0) == BST_CHECKED; float outlineSize = (float)SendMessage(GetDlgItem(hwnd, IDC_OUTLINETHICKNESS), UDM_GETPOS32, 0, 0); int mode = SendMessage(GetDlgItem(hwnd, IDC_USEFILE), BM_GETCHECK, 0, 0) == BST_CHECKED; String strText = GetEditText(GetDlgItem(hwnd, IDC_TEXT)); String strFile = GetEditText(GetDlgItem(hwnd, IDC_FILE)); UINT extentWidth = (UINT)SendMessage(GetDlgItem(hwnd, IDC_EXTENTWIDTH), UDM_GETPOS32, 0, 0); UINT extentHeight = (UINT)SendMessage(GetDlgItem(hwnd, IDC_EXTENTHEIGHT), UDM_GETPOS32, 0, 0); String strFont = GetFontFace(configInfo, GetDlgItem(hwnd, IDC_FONT)); UINT fontSize = (UINT)SendMessage(GetDlgItem(hwnd, IDC_TEXTSIZE), UDM_GETPOS32, 0, 0); BOOL bBold = SendMessage(GetDlgItem(hwnd, IDC_BOLD), BM_GETCHECK, 0, 0) == BST_CHECKED; BOOL bItalic = SendMessage(GetDlgItem(hwnd, IDC_ITALIC), BM_GETCHECK, 0, 0) == BST_CHECKED; BOOL bVertical = SendMessage(GetDlgItem(hwnd, IDC_VERTICALSCRIPT), BM_GETCHECK, 0, 0) == BST_CHECKED; BOOL pointFiltering = SendMessage(GetDlgItem(hwnd, IDC_POINTFILTERING), BM_GETCHECK, 0, 0) == BST_CHECKED; String strFontDisplayName = GetEditText(GetDlgItem(hwnd, IDC_FONT)); if(strFont.IsEmpty()) { UINT id = FindFontName(configInfo, GetDlgItem(hwnd, IDC_FONT), strFontDisplayName); if(id != INVALID) strFont = configInfo->fontFaces[id]; } if(strFont.IsEmpty()) { String strError = Str("Sources.TextSource.FontNotFound"); strError.FindReplace(TEXT("$1"), strFontDisplayName); OBSMessageBox(hwnd, strError, NULL, 0); break; } if(bUseTextExtents) { configInfo->cx = float(extentWidth); configInfo->cy = float(extentHeight); } else { String strOutputText; if(mode == 0) strOutputText = strText; else if(mode == 1) { XFile textFile; if(strFile.IsEmpty() || !textFile.Open(strFile, XFILE_READ | XFILE_SHARED, XFILE_OPENEXISTING)) { String strError = Str("Sources.TextSource.FileNotFound"); strError.FindReplace(TEXT("$1"), strFile); OBSMessageBox(hwnd, strError, NULL, 0); break; } textFile.ReadFileToString(strOutputText); } LOGFONT lf; zero(&lf, sizeof(lf)); lf.lfHeight = fontSize; lf.lfWeight = bBold ? FW_BOLD : FW_DONTCARE; lf.lfItalic = bItalic; lf.lfQuality = ANTIALIASED_QUALITY; if(strFont.IsValid()) scpy_n(lf.lfFaceName, strFont, 31); else scpy_n(lf.lfFaceName, TEXT("Arial"), 31); HDC hDC = CreateCompatibleDC(NULL); Gdiplus::Font font(hDC, &lf); if(!font.IsAvailable()) { String strError = Str("Sources.TextSource.FontNotFound"); strError.FindReplace(TEXT("$1"), strFontDisplayName); OBSMessageBox(hwnd, strError, NULL, 0); DeleteDC(hDC); break; } { Gdiplus::Graphics graphics(hDC); Gdiplus::StringFormat format(Gdiplus::StringFormat::GenericTypographic()); UINT formatFlags; formatFlags = Gdiplus::StringFormatFlagsNoFitBlackBox | Gdiplus::StringFormatFlagsMeasureTrailingSpaces; if(bVertical) formatFlags |= Gdiplus::StringFormatFlagsDirectionVertical | Gdiplus::StringFormatFlagsDirectionRightToLeft; format.SetFormatFlags(formatFlags); format.SetTrimming(Gdiplus::StringTrimmingWord); Gdiplus::RectF rcf; graphics.MeasureString(strOutputText, -1, &font, Gdiplus::PointF(0.0f, 0.0f), &format, &rcf); if(bUseOutline) { rcf.Height += outlineSize; rcf.Width += outlineSize; } if(bVertical) { if(rcf.Widthcx = MAX(rcf.Width, 32.0f); configInfo->cy = MAX(rcf.Height, 32.0f); } DeleteDC(hDC); } data->SetFloat(TEXT("baseSizeCX"), configInfo->cx); data->SetFloat(TEXT("baseSizeCY"), configInfo->cy); data->SetString(TEXT("font"), strFont); data->SetInt(TEXT("color"), CCGetColor(GetDlgItem(hwnd, IDC_COLOR))); data->SetInt(TEXT("fontSize"), fontSize); data->SetInt(TEXT("textOpacity"), (UINT)SendMessage(GetDlgItem(hwnd, IDC_TEXTOPACITY), UDM_GETPOS32, 0, 0)); data->SetInt(TEXT("scrollSpeed"), (int)SendMessage(GetDlgItem(hwnd, IDC_SCROLLSPEED), UDM_GETPOS32, 0, 0)); data->SetInt(TEXT("bold"), bBold); data->SetInt(TEXT("italic"), bItalic); data->SetInt(TEXT("vertical"), bVertical); data->SetInt(TEXT("wrap"), SendMessage(GetDlgItem(hwnd, IDC_WRAP), BM_GETCHECK, 0, 0) == BST_CHECKED); data->SetInt(TEXT("scrollMode"), SendMessage(GetDlgItem(hwnd, IDC_SCROLLMODE), BM_GETCHECK, 0, 0) == BST_CHECKED); data->SetInt(TEXT("underline"), SendMessage(GetDlgItem(hwnd, IDC_UNDERLINE), BM_GETCHECK, 0, 0) == BST_CHECKED); data->SetInt(TEXT("pointFiltering"), pointFiltering); data->SetInt(TEXT("backgroundColor"), CCGetColor(GetDlgItem(hwnd, IDC_BACKGROUNDCOLOR))); data->SetInt(TEXT("backgroundOpacity"), (UINT)SendMessage(GetDlgItem(hwnd, IDC_BACKGROUNDOPACITY), UDM_GETPOS32, 0, 0)); data->SetInt(TEXT("useOutline"), bUseOutline); data->SetInt(TEXT("outlineColor"), CCGetColor(GetDlgItem(hwnd, IDC_OUTLINECOLOR))); data->SetFloat(TEXT("outlineSize"), outlineSize); data->SetInt(TEXT("outlineOpacity"), (UINT)SendMessage(GetDlgItem(hwnd, IDC_OUTLINEOPACITY), UDM_GETPOS32, 0, 0)); data->SetInt(TEXT("useTextExtents"), bUseTextExtents); data->SetInt(TEXT("extentWidth"), extentWidth); data->SetInt(TEXT("extentHeight"), extentHeight); data->SetInt(TEXT("align"), (int)SendMessage(GetDlgItem(hwnd, IDC_ALIGN), CB_GETCURSEL, 0, 0)); data->SetString(TEXT("file"), strFile); data->SetString(TEXT("text"), strText); data->SetInt(TEXT("mode"), mode); } case IDCANCEL: if(LOWORD(wParam) == IDCANCEL) DoCancelStuff(hwnd); EndDialog(hwnd, LOWORD(wParam)); } break; case WM_CLOSE: DoCancelStuff(hwnd); EndDialog(hwnd, IDCANCEL); } return 0; } bool STDCALL ConfigureTextSource(XElement *element, bool bCreating) { if(!element) { AppWarning(TEXT("ConfigureTextSource: NULL element")); return false; } XElement *data = element->GetElement(TEXT("data")); if(!data) data = element->CreateElement(TEXT("data")); ConfigTextSourceInfo configInfo; configInfo.lpName = element->GetName(); configInfo.data = data; if(OBSDialogBox(hinstMain, MAKEINTRESOURCE(IDD_CONFIGURETEXTSOURCE), hwndMain, ConfigureTextProc, (LPARAM)&configInfo) == IDOK) { element->SetFloat(TEXT("cx"), configInfo.cx); element->SetFloat(TEXT("cy"), configInfo.cy); return true; } return false; }