LRESULT CWindow::OnPaint(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { int iLineCount, iColumnCount; PAINTSTRUCT ps; BeginPaint(hWnd, &ps); iLineCount = cyClient / cyChar; iColumnCount = cxClient / cxChar; SelectObject(ps.hdc, m_hFont); for (UInt32 i = 0, j = min(countof(szErrorString), iLineCount); i != j; ++i) { int len = lstrlen(szErrorString[i + iVScrollPos]); if (i + iVScrollPos < countof(szErrorString)) { TextOut(ps.hdc, 10, i * cyChar, szErrorString[i + iVScrollPos], min(len, iColumnCount)); } } PBYTE pbBuffer; DWORD dwSize; GLYPHMETRICS gm; MAT2 m2 = { {0, 1}, {0, 0}, {0, 0}, {0, 1} }; BYTE m_matrix[32]; char buf[100]; dwSize = GetGlyphOutlineA(ps.hdc, 0xB8DF, GGO_BITMAP, &gm, 0, NULL, &m2); if (dwSize != GDI_ERROR) { pbBuffer = (PBYTE)malloc(dwSize); GetGlyphOutlineA(ps.hdc, 0xB8DF, GGO_BITMAP, &gm, dwSize, pbBuffer, &m2); for(DWORD i = 0; i < dwSize / 4; ++i) { m_matrix[i*2] = pbBuffer[4*i]; m_matrix[i*2+1] = pbBuffer[4*i+1]; wsprintf(buf, "0x%02X 0x%02X", m_matrix[i*2], m_matrix[i*2+1]); } free(pbBuffer); } wsprintf(buf, "%d", GetDeviceCaps(ps.hdc, PLANES) * GetDeviceCaps(ps.hdc, BITSPIXEL)); SetWindowText(hWnd, buf); GetNearestColor(ps.hdc, RGB(123, 321, 123)); EndPaint(hWnd, &ps); return ERROR_SUCCESS; }
/*********************************************************************** * wglUseFontOutlines_common */ static BOOL wglUseFontOutlines_common(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf, BOOL unicode) { UINT glyph; const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}}; GLUtesselator *tess; LOGFONTW lf; HFONT old_font, unscaled_font; UINT em_size = 1024; RECT rc; TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count, listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A"); if (!load_libglu()) { ERR("libGLU is required for this function but isn't loaded\n"); return FALSE; } ENTER_GL(); tess = pgluNewTess(); if(tess) { pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex); pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin); pgluTessCallback(tess, GLU_TESS_END, tess_callback_end); } LEAVE_GL(); if(!tess) return FALSE; GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf); rc.left = rc.right = rc.bottom = 0; rc.top = em_size; DPtoLP(hdc, (POINT*)&rc, 2); lf.lfHeight = -abs(rc.top - rc.bottom); lf.lfOrientation = lf.lfEscapement = 0; unscaled_font = CreateFontIndirectW(&lf); old_font = SelectObject(hdc, unscaled_font); for (glyph = first; glyph < first + count; glyph++) { DWORD needed; GLYPHMETRICS gm; BYTE *buf; TTPOLYGONHEADER *pph; TTPOLYCURVE *ppc; GLdouble *vertices; if(unicode) needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity); else needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity); if(needed == GDI_ERROR) goto error; buf = HeapAlloc(GetProcessHeap(), 0, needed); vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble)); if(unicode) GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity); else GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity); TRACE("glyph %d\n", glyph); if(lpgmf) { lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size; lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size; lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size; lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size; lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size; lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size; TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY, lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY); lpgmf++; } ENTER_GL(); glNewList(listBase++, GL_COMPILE); pgluTessBeginPolygon(tess, NULL); pph = (TTPOLYGONHEADER*)buf; while((BYTE*)pph < buf + needed) { TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value); pgluTessBeginContour(tess); fixed_to_double(pph->pfxStart, em_size, vertices); pgluTessVertex(tess, vertices, vertices); vertices += 3; ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph)); while((char*)ppc < (char*)pph + pph->cb) { int i; switch(ppc->wType) { case TT_PRIM_LINE: for(i = 0; i < ppc->cpfx; i++) { TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value); fixed_to_double(ppc->apfx[i], em_size, vertices); pgluTessVertex(tess, vertices, vertices); vertices += 3; } break; case TT_PRIM_QSPLINE: for(i = 0; i < ppc->cpfx/2; i++) { /* FIXME just connecting the control points for now */ TRACE("\t\tcurve %d,%d %d,%d\n", ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value, ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value); fixed_to_double(ppc->apfx[i * 2], em_size, vertices); pgluTessVertex(tess, vertices, vertices); vertices += 3; fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices); pgluTessVertex(tess, vertices, vertices); vertices += 3; } break; default: ERR("\t\tcurve type = %d\n", ppc->wType); pgluTessEndContour(tess); goto error_in_list; } ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) + (ppc->cpfx - 1) * sizeof(POINTFX)); } pgluTessEndContour(tess); pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb); } error_in_list: pgluTessEndPolygon(tess); glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0); glEndList(); LEAVE_GL(); HeapFree(GetProcessHeap(), 0, buf); HeapFree(GetProcessHeap(), 0, vertices); } error: DeleteObject(SelectObject(hdc, old_font)); pgluDeleteTess(tess); return TRUE; }