INT_PTR CALLBACK FrameServerSetupDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_INITDIALOG: { char buf[32]; ivdsl->GetComputerName(buf); strcat(buf,"/"); SetDlgItemText(hDlg, IDC_COMPUTER_NAME, buf); } SetDlgItemText(hDlg, IDC_FSNAME, VDTextWToA(VDFileSplitPath(g_szInputAVIFile)).c_str()); SetWindowLongPtr(hDlg, DWLP_USER, lParam); return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: SendDlgItemMessage(hDlg, IDC_FSNAME, WM_GETTEXT, 128, GetWindowLongPtr(hDlg, DWLP_USER)); EndDialog(hDlg, TRUE); break; case IDCANCEL: EndDialog(hDlg, FALSE); break; } break; } return FALSE; }
void VDInputFileImages::Init(const wchar_t *szFile) { // Attempt to discern path format. // // First, find the start of the filename. Then skip // backwards until the first period is found, then to the // beginning of the first number. mBaseName = szFile; const wchar_t *pszBaseFormat = mBaseName.c_str(); const wchar_t *pszFileBase = VDFileSplitPath(pszBaseFormat); const wchar_t *s = pszFileBase; mLastDigitPos = -1; while(*s) ++s; while(s > pszFileBase && s[-1] != L'.') --s; while(s > pszFileBase) { --s; if (iswdigit(*s)) { mLastDigitPos = s - pszBaseFormat; break; } } mFrames = 1; // Make sure the first file exists. vdfastvector<wchar_t> namebuf; if (!VDDoesPathExist(ComputeFilename(namebuf, 0))) throw MyError("File \"%ls\" does not exist.", namebuf.data()); // Stat as many files as we can until we get an error. if (mLastDigitPos >= 0) { vdfastvector<wchar_t> namebuf; ProgressDialog pd(g_hWnd, "Image import filter", "Scanning for images", 0x3FFFFFFF, true); pd.setValueFormat("Scanning frame %lu"); while(VDDoesPathExist(ComputeFilename(namebuf, mFrames))) { ++mFrames; pd.advance((long)mFrames); } } // make sure the first frame is valid vdrefptr<IVDVideoSource> vs; GetVideoSource(0, ~vs); }
void VDUIDialogPlugins::PluginItem::GetText(int subItem, VDStringW& s) const { switch(subItem) { case 0: s = VDFileSplitPath(mpDesc->mpModule->GetFilename().c_str()); break; case 1: s = L"Plugin"; break; case 2: s = mpDesc->mName.c_str(); break; } }
void VDUIDialogPlugins::FilterItem::GetText(int subItem, VDStringW& s) const { switch(subItem) { case 0: { VDExternalModule *module = mpFDI->GetModule(); if (module) s = VDFileSplitPath(module->GetFilename().c_str()); else s = L"(internal)"; } break; case 1: s = L"Video filter"; break; case 2: s = VDTextAToW(mpFDI->GetName()); break; } }
void AppendAVIAutoscan(const wchar_t *pszFile) { wchar_t buf[MAX_PATH]; wchar_t *s = buf, *t; int count = 0; if (!inputAVI) return; IVDStreamSource *pVSS = inputVideo->asStream(); VDPosition originalCount = pVSS->getEnd(); wcscpy(buf, pszFile); t = VDFileSplitExt(VDFileSplitPath(s)); if (t>buf) --t; try { for(;;) { if (!VDDoesPathExist(buf)) break; if (!inputAVI->Append(buf)) break; ++count; s = t; for(;;) { if (s<buf || !isdigit(*s)) { memmove(s+2, s+1, sizeof(wchar_t) * wcslen(s)); s[1] = L'1'; ++t; } else { if (*s == L'9') { *s-- = L'0'; continue; } ++*s; } break; } } } catch(const MyError& e) { // if the first segment failed, turn the warning into an error if (!count) throw; // log append errors, but otherwise eat them VDLog(kVDLogWarning, VDTextAToW(e.gets())); } guiSetStatus("Appended %d segments (stopped at \"%s\")", 255, count, VDTextWToA(buf).c_str()); if (count) { FrameSubset& s = g_project->GetTimeline().GetSubset(); g_project->BeginTimelineUpdate(); s.insert(s.end(), FrameSubsetNode(originalCount, pVSS->getEnd() - originalCount, false, 0)); g_project->EndTimelineUpdate(); } }
void VDUIJobControlDialog::GetJobListDispInfoW(NMLVDISPINFOW *nldi) { VDJob *vdj = g_VDJobQueue.ListGet(nldi->item.iItem); SYSTEMTIME st; SYSTEMTIME ct; static const wchar_t *const dow[]={L"Sun",L"Mon",L"Tue",L"Wed",L"Thu",L"Fri",L"Sat"}; if (!(nldi->item.mask & LVIF_TEXT)) return; nldi->item.mask = LVIF_TEXT; nldi->item.pszText[0] = 0; if (!vdj) return; uint64 *ft = &vdj->mDateEnd; switch(nldi->item.iSubItem) { case 0: VDTextAToW(nldi->item.pszText, nldi->item.cchTextMax, vdj->GetName()); break; case 1: // file in VDTextAToW(nldi->item.pszText, nldi->item.cchTextMax, VDFileSplitPath(vdj->GetInputFile())); break; case 2: // file out VDTextAToW(nldi->item.pszText, nldi->item.cchTextMax, VDFileSplitPath(vdj->GetOutputFile())); break; case 3: // time in ft = &vdj->mDateStart; case 4: // time out { FILETIME ft2, ftl; ft2.dwLowDateTime = (uint32)*ft; ft2.dwHighDateTime = (uint32)(*ft >> 32); FileTimeToLocalFileTime(&ft2, &ftl); FileTimeToSystemTime(&ftl, &st); } GetLocalTime(&ct); if (!*ft) nldi->item.pszText = L"-"; else if (ct.wYear != st.wYear || ct.wMonth != st.wMonth || ct.wDay != st.wDay) { swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"%s %d %d:%02d%c" ,dow[st.wDayOfWeek] ,st.wDay ,st.wHour==12||!st.wHour ? 12 : st.wHour%12 ,st.wMinute ,st.wHour>=12 ? 'p' : 'a'); } else { swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"%d:%02d%c" ,st.wHour==12||!st.wHour ? 12 : st.wHour%12 ,st.wMinute ,st.wHour>=12 ? 'p' : 'a'); } break; case 5: // status switch(vdj->GetState()) { case VDJob::kStateWaiting: nldi->item.pszText = L"Waiting" ; break; case VDJob::kStateInProgress: if (vdj->mRunnerName.empty() || vdj->IsLocal()) nldi->item.pszText = L"In progress"; else swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"In progress (%hs:%d)", vdj->mRunnerName.c_str(), (uint32)vdj->GetRunnerId()); break; case VDJob::kStateStarting: if (vdj->mRunnerName.empty() || vdj->IsLocal()) nldi->item.pszText = L"Starting"; else swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"Starting (%hs:%d)", vdj->mRunnerName.c_str(), (uint32)vdj->GetRunnerId()); break; case VDJob::kStateAborting: if (vdj->mRunnerName.empty() || vdj->IsLocal()) nldi->item.pszText = L"Aborting"; else swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"Aborting (%hs:%d)", vdj->mRunnerName.c_str(), (uint32)vdj->GetRunnerId()); break; case VDJob::kStateCompleted: if (vdj->mRunnerName.empty() || vdj->IsLocal()) swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"Done%hs", vdj->mLogEntries.empty() ? "" : " (warnings)"); else swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"Done%hs (%hs:%d)", vdj->mLogEntries.empty() ? "" : " (warnings)", vdj->mRunnerName.c_str(), (uint32)vdj->GetRunnerId()); break; case VDJob::kStatePostponed: nldi->item.pszText = L"Postponed"; break; case VDJob::kStateAborted: if (vdj->mRunnerName.empty() || vdj->IsLocal()) nldi->item.pszText = L"Aborted"; else swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"Aborted (%hs:%d)", vdj->mRunnerName.c_str(), (uint32)vdj->GetRunnerId()); break; case VDJob::kStateError: if (vdj->mRunnerName.empty() || vdj->IsLocal()) nldi->item.pszText = L"Error"; else swprintf(nldi->item.pszText, nldi->item.cchTextMax, L"Error (%hs:%d)", vdj->mRunnerName.c_str(), (uint32)vdj->GetRunnerId()); break; } break; } }
void tool_fontextract(const vdfastvector<const char *>& args, const vdfastvector<const char *>& switches) { if (args.size() < 6) help_fontextract(); printf("Asuka: Extracting font: %s -> %s.\n", args[0], args[4]); int startChar; int endChar; if (1 != sscanf(args[2], "%d", &startChar) || 1 != sscanf(args[3], "%d", &endChar)) help_fontextract(); if (startChar < 0 || endChar > 0xFFFF || endChar <= startChar) { printf("Asuka: Invalid character range %d-%d\n", startChar, endChar); exit(10); } int fontsAdded = AddFontResourceEx(args[0], FR_NOT_ENUM | FR_PRIVATE, 0); if (!fontsAdded) { printf("Asuka: Unable to load font file: %s\n", args[0]); exit(10); } HFONT hfont = CreateFontA(10, 0, 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, args[1]); if (!hfont) { printf("Asuka: Unable to instantiate font: %s\n", args[1]); exit(10); } HDC hdc = CreateDC("DISPLAY", 0, 0, 0); HGDIOBJ hfontOld = SelectObject(hdc, hfont); MAT2 m = { {0,1},{0,0},{0,0},{0,1} }; union { OUTLINETEXTMETRICW m; char buf[2048]; } metrics; if (!GetOutlineTextMetricsW(hdc, sizeof metrics, &metrics.m)) { printf("Asuka: Unable to retrieve outline text metrics.\n"); exit(10); } SelectObject(hdc, hfontOld); DeleteObject(hfont); hfont = CreateFontA(metrics.m.otmEMSquare, 0, 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, args[1]); if (!hfont) { printf("Asuka: Unable to instantiate font: %s\n", args[1]); exit(10); } hfontOld = SelectObject(hdc, hfont); if (!GetOutlineTextMetricsW(hdc, sizeof metrics, &metrics.m)) { printf("Asuka: Unable to retrieve outline text metrics.\n"); exit(10); } FILE *f = fopen(args[4], "w"); if (!f) { printf("Asuka: Unable to open output file: %s\n", args[4]); exit(10); } std::vector<GlyphInfo> glyphs(endChar - startChar + 1); sint32 minX = 0x7FFFFFFF; sint32 minY = 0x7FFFFFFF; sint32 maxX = -0x7FFFFFFF - 1; sint32 maxY = -0x7FFFFFFF - 1; vdfastvector<sint32> points; vdfastvector<uint8> commands; for(int c=startChar; c<endChar; ++c) { GlyphInfo& info = glyphs[c - startChar]; info.mPointStart = points.size() >> 1; info.mCommandStart = commands.size(); GetCharABCWidthsFloatW(hdc, c, c, &info.mWidths); // encode glyph outline GLYPHMETRICS gm; if (GDI_ERROR == GetGlyphOutlineW(hdc, c, GGO_METRICS, &gm, 0, NULL, &m)) { printf("Asuka: Unable to obtain glyph metrics for char %d.\n", c); exit(20); } DWORD dwBytes = GetGlyphOutlineW(hdc, c, GGO_NATIVE | GGO_UNHINTED, &gm, 0, NULL, &m); if (dwBytes == 0xFFFFFFFF) { printf("Asuka: Unable to obtain glyph outline for char %d.\n", c); exit(20); } // GetGlyphOutline() doesn't like providing results for spaces. if (gm.gmBlackBoxX <= 0 || gm.gmBlackBoxY <= 0) continue; void *buf = malloc(dwBytes); GetGlyphOutlineW(hdc, c, GGO_NATIVE | GGO_UNHINTED, &gm, dwBytes, buf, &m); void *limit = (char *)buf + dwBytes; TTPOLYGONHEADER *pHdr = (TTPOLYGONHEADER *)buf; sint32 lastCode = 0; while(pHdr != limit) { VDASSERT(pHdr->dwType == TT_POLYGON_TYPE); sint32 x = *(const sint32 *)&pHdr->pfxStart.x; sint32 y = *(const sint32 *)&pHdr->pfxStart.y; if (minX > x) minX = x; if (minY > y) minY = y; if (maxX < x) maxX = x; if (maxY < y) maxY = y; points.push_back(x); points.push_back(y); TTPOLYCURVE *pCurve = (TTPOLYCURVE *)(pHdr + 1); TTPOLYCURVE *pCurveEnd = (TTPOLYCURVE *)((char *)pHdr + pHdr->cb); while(pCurve != pCurveEnd) { VDASSERT(pCurve->wType == TT_PRIM_QSPLINE || pCurve->wType == TT_PRIM_LINE); POINTFX *ppfx = pCurve->apfx; for(int i=0; i<pCurve->cpfx; ++i) { sint32 x = *(const sint32 *)&ppfx->x; sint32 y = *(const sint32 *)&ppfx->y; if (minX > x) minX = x; if (minY > y) minY = y; if (maxX < x) maxX = x; if (maxY < y) maxY = y; points.push_back(x); points.push_back(y); ++ppfx; } if (pCurve->wType == TT_PRIM_LINE) { if ((lastCode & 3) != 2) { if (lastCode) commands.push_back(lastCode); lastCode = 2 - 4; } for(int i=0; i<pCurve->cpfx; ++i) { if (lastCode >= 0x7C) { commands.push_back(lastCode); lastCode = 2 - 4; } lastCode += 4; } } else { VDASSERT(pCurve->wType == TT_PRIM_QSPLINE); VDASSERT(!(pCurve->cpfx % 2)); if ((lastCode & 3) != 3) { if (lastCode) commands.push_back(lastCode); lastCode = 3 - 4; } for(int i=0; i<pCurve->cpfx; i+=2) { if (lastCode >= 0x7C) { commands.push_back(lastCode); lastCode = 3 - 4; } lastCode += 4; } } pCurve = (TTPOLYCURVE *)ppfx; } if (lastCode) { commands.push_back(lastCode | 0x80); lastCode = 0; } vdptrstep(pHdr, pHdr->cb); } free(buf); } GlyphInfo& lastInfo = glyphs.back(); lastInfo.mPointStart = points.size() >> 1; lastInfo.mCommandStart = commands.size(); // write points fprintf(f, "// Created by Asuka from %s. DO NOT EDIT!\n\n", VDFileSplitPath(args[0])); fprintf(f, "const uint16 %s_FontPointArray[]={\n", args[5]); float scaleX = (maxX > minX) ? 1.0f / (maxX - minX) : 0.0f; float scaleY = (maxY > minY) ? 1.0f / (maxY - minY) : 0.0f; int pointElementCount = points.size(); for(int i=0; i<pointElementCount; i+=2) { uint8 x = VDClampedRoundFixedToUint8Fast((float)(points[i+0] - minX) * scaleX); uint8 y = VDClampedRoundFixedToUint8Fast((float)(points[i+1] - minY) * scaleY); uint16 pt = ((uint16)y << 8) + x; fprintf(f, "0x%04x,", pt); if ((i & 30) == 30) putc('\n', f); } if (pointElementCount & 30) putc('\n', f); fprintf(f, "};\n\n"); // write commands fprintf(f, "const uint8 %s_FontCommandArray[]={\n", args[5]); int commandElementCount = commands.size(); for(int i=0; i<commandElementCount; ++i) { fprintf(f, "0x%02x,", commands[i]); if ((i & 15) == 15) putc('\n', f); } if (commandElementCount & 15) putc('\n', f); fprintf(f, "};\n\n"); // glyph data structures fprintf(f, "const VDOutlineFontGlyphInfo %s_FontGlyphArray[]={\n", args[5]); for(int i=startChar; i<=endChar; ++i) { const GlyphInfo& info = glyphs[i - startChar]; fprintf(f, "{ %d, %d, %d, %d, %d },\n", info.mPointStart, info.mCommandStart, VDRoundToInt(info.mWidths.abcfA), VDRoundToInt(info.mWidths.abcfB), VDRoundToInt(info.mWidths.abcfC)); } fprintf(f, "};\n\n"); // top-level data structure fprintf(f, "const VDOutlineFontInfo %s_FontInfo={\n", args[5]); fprintf(f, "\t%s_FontPointArray,\n", args[5]); fprintf(f, "\t%s_FontCommandArray,\n", args[5]); fprintf(f, "\t%s_FontGlyphArray,\n", args[5]); fprintf(f, "\t%d, %d,\n", startChar, endChar); fprintf(f, "\t%d, %d, %d, %d,\t// bounds (16:16)\n", minX, minY, maxX, maxY); fprintf(f, "\t%d,\t// em square\n", metrics.m.otmEMSquare); fprintf(f, "\t%d,\t// ascent\n", metrics.m.otmAscent); fprintf(f, "\t%d,\t// descent\n", metrics.m.otmDescent); fprintf(f, "\t%d,\t// line gap\n", metrics.m.otmLineGap); fprintf(f, "};\n"); printf("Asuka: %d point bytes, %d command bytes, %d glyph info bytes.\n", (int)points.size(), (int)commands.size(), (endChar - startChar + 1) * 10); SelectObject(hdc, hfontOld); DeleteDC(hdc); DeleteObject(hfont); }
VDString VDFileSplitPathRight(const VDString& s) { return splitimpR(s, VDFileSplitPath(s.c_str())); }
VDStringW VDFileSplitPathLeft (const VDStringW& s) { return splitimpL(s, VDFileSplitPath(s.c_str())); }