COLORREF AdjustLightness(COLORREF c, float factor) { BYTE R = GetRValueSafe(c), G = GetGValueSafe(c), B = GetBValueSafe(c); // cf. http://en.wikipedia.org/wiki/HSV_color_space#Hue_and_chroma BYTE M = max(max(R, G), B), m = min(min(R, G), B); if (M == m) { // for grayscale values, lightness is proportional to the color value BYTE X = (BYTE)limitValue((int)floorf(M * factor + 0.5f), 0, 255); return RGB(X, X, X); } BYTE C = M - m; BYTE Ha = (BYTE)abs(M == R ? G - B : M == G ? B - R : R - G); // cf. http://en.wikipedia.org/wiki/HSV_color_space#Lightness float L2 = (float)(M + m); // cf. http://en.wikipedia.org/wiki/HSV_color_space#Saturation float S = C / (L2 > 255.0f ? 510.0f - L2 : L2); L2 = limitValue(L2 * factor, 0.0f, 510.0f); // cf. http://en.wikipedia.org/wiki/HSV_color_space#From_HSL float C1 = (L2 > 255.0f ? 510.0f - L2 : L2) * S; float X1 = C1 * Ha / C; float m1 = (L2 - C1) / 2; R = (BYTE)floorf((M == R ? C1 : m != R ? X1 : 0) + m1 + 0.5f); G = (BYTE)floorf((M == G ? C1 : m != G ? X1 : 0) + m1 + 0.5f); B = (BYTE)floorf((M == B ? C1 : m != B ? X1 : 0) + m1 + 0.5f); return RGB(R, G, B); }
virtual void update(int inKey) { // TODO: AT_ASSERT mValuePtr != 0... T & valRef = *mValuePtr; switch(inKey) { case 45: /*-*/ case KEY_LEFT: /*<-*/ if (mStepMode == StepModeT::LINEAR) { valRef -= mSteps; valRef = limitValue(valRef); if (mUpdateFunc) { mUpdateFunc(& valRef); } } else if (mStepMode == StepModeT::FACTOR) { if (mSteps) { valRef /= mSteps; valRef = limitValue(valRef); if (mUpdateFunc) { mUpdateFunc(& valRef); } } } else { // Not implemented -> TODO: AT_ASSERT } break; case 43: /*+*/ case KEY_RIGHT: /*+*/ if (mStepMode == StepModeT::LINEAR) { valRef += mSteps; valRef = limitValue(valRef); if (mUpdateFunc) { mUpdateFunc(& valRef); } } else if (mStepMode == StepModeT::FACTOR) { valRef *= mSteps; valRef = limitValue(valRef); if (mUpdateFunc) { mUpdateFunc(& valRef); } } else { // Not implemented -> TODO: AT_ASSERT } break; case 27: /*ESC*/ { if (mAbortFunc) { mAbortFunc(); } } default: /* nothing */ break; } }
static void ApplyPrintSettings(const WCHAR *settings, int pageCount, Vec<PRINTPAGERANGE> &ranges, Print_Advanced_Data &advanced, LPDEVMODE devMode) { WStrVec rangeList; if (settings) rangeList.Split(settings, L",", true); for (size_t i = 0; i < rangeList.Count(); i++) { int val; PRINTPAGERANGE pr; if (str::Parse(rangeList.At(i), L"%d-%d%$", &pr.nFromPage, &pr.nToPage)) { pr.nFromPage = limitValue(pr.nFromPage, (DWORD)1, (DWORD)pageCount); pr.nToPage = limitValue(pr.nToPage, (DWORD)1, (DWORD)pageCount); ranges.Append(pr); } else if (str::Parse(rangeList.At(i), L"%d%$", &pr.nFromPage)) { pr.nFromPage = pr.nToPage = limitValue(pr.nFromPage, (DWORD)1, (DWORD)pageCount); ranges.Append(pr); } else if (str::EqI(rangeList.At(i), L"even")) advanced.range = PrintRangeEven; else if (str::EqI(rangeList.At(i), L"odd")) advanced.range = PrintRangeOdd; else if (str::EqI(rangeList.At(i), L"noscale")) advanced.scale = PrintScaleNone; else if (str::EqI(rangeList.At(i), L"shrink")) advanced.scale = PrintScaleShrink; else if (str::EqI(rangeList.At(i), L"fit")) advanced.scale = PrintScaleFit; else if (str::Parse(rangeList.At(i), L"%dx%$", &val) && 0 < val && val < 1000) devMode->dmCopies = (short)val; else if (str::EqI(rangeList.At(i), L"simplex")) devMode->dmDuplex = DMDUP_SIMPLEX; else if (str::EqI(rangeList.At(i), L"duplex") || str::EqI(rangeList.At(i), L"duplexlong")) devMode->dmDuplex = DMDUP_VERTICAL; else if (str::EqI(rangeList.At(i), L"duplexshort")) devMode->dmDuplex = DMDUP_HORIZONTAL; else if (str::EqI(rangeList.At(i), L"color")) devMode->dmColor = DMCOLOR_COLOR; else if (str::EqI(rangeList.At(i), L"monochrome")) devMode->dmColor = DMCOLOR_MONOCHROME; else if (str::StartsWithI(rangeList.At(i), L"bin=")) devMode->dmDefaultSource = GetPaperSourceByName(rangeList.At(i) + 4, devMode); else if (str::StartsWithI(rangeList.At(i), L"paper=")) devMode->dmPaperSize = GetPaperByName(rangeList.At(i) + 6); } if (ranges.Count() == 0) { PRINTPAGERANGE pr = { 1, (DWORD)pageCount }; ranges.Append(pr); } }
// Adjusts lightness by 1/255 units. COLORREF AdjustLightness2(COLORREF c, float units) { float lightness = GetLightness(c); units = limitValue(units, -lightness, 255.0f - lightness); if (0.0f == lightness) return RGB(BYTE(units + 0.5f), BYTE(units + 0.5f), BYTE(units + 0.5f)); return AdjustLightness(c, 1.0f + units / lightness); }
void HtmlFormatter::HandleTagFont(HtmlToken* t) { if (t->IsEndTag()) { RevertStyleChange(); return; } AttrInfo* attr = t->GetAttrByName("face"); const WCHAR* faceName = CurrFont()->GetName(); if (attr) { size_t strLen = str::Utf8ToWcharBuf(attr->val, attr->valLen, buf, dimof(buf)); // multiple font names can be comma separated if (strLen > 0 && *buf != ',') { str::TransChars(buf, L",", L"\0"); faceName = buf; } } float fontSize = CurrFont()->GetSize(); attr = t->GetAttrByName("size"); if (attr) { // the sizes are in the range from 1 (tiny) to 7 (huge) int size = 3; // normal size str::Parse(attr->val, attr->valLen, "%d", &size); // sizes can also be relative to the current size if (attr->valLen > 0 && ('-' == *attr->val || '+' == *attr->val)) size += 3; size = limitValue(size, 1, 7); float scale = pow(1.2f, size - 3); fontSize = defaultFontSize * scale; } SetFont(faceName, (FontStyle)CurrFont()->GetStyle(), fontSize); }
bool FLIConverter::setProgressPercentage(int n) { limitValue(n, 0, 100); if (n != prvProgressPercentage) { prvProgressPercentage = n; return progressPercentageCallback(progressPercentageUserData, n); } return true; }
void ChmModel::SetZoomVirtual(float zoom, PointI *fixPt) { if (zoom > 0) zoom = limitValue(zoom, ZOOM_MIN, ZOOM_MAX); if (zoom <= 0 || !IsValidZoom(zoom)) zoom = 100.0f; ZoomTo(zoom); initZoom = zoom; }
static void ApplyPrintSettings(const WCHAR *settings, int pageCount, Vec<PRINTPAGERANGE>& ranges, Print_Advanced_Data& advanced, LPDEVMODE devMode) { WStrVec rangeList; if (settings) rangeList.Split(settings, L",", true); for (size_t i = 0; i < rangeList.Count(); i++) { int val; PRINTPAGERANGE pr; if (str::Parse(rangeList.At(i), L"%d-%d%$", &pr.nFromPage, &pr.nToPage)) { pr.nFromPage = limitValue(pr.nFromPage, (DWORD)1, (DWORD)pageCount); pr.nToPage = limitValue(pr.nToPage, (DWORD)1, (DWORD)pageCount); ranges.Append(pr); } else if (str::Parse(rangeList.At(i), L"%d%$", &pr.nFromPage)) { pr.nFromPage = pr.nToPage = limitValue(pr.nFromPage, (DWORD)1, (DWORD)pageCount); ranges.Append(pr); } else if (str::Eq(rangeList.At(i), L"even")) advanced.range = PrintRangeEven; else if (str::Eq(rangeList.At(i), L"odd")) advanced.range = PrintRangeOdd; else if (str::Eq(rangeList.At(i), L"noscale")) advanced.scale = PrintScaleNone; else if (str::Eq(rangeList.At(i), L"shrink")) advanced.scale = PrintScaleShrink; else if (str::Eq(rangeList.At(i), L"fit")) advanced.scale = PrintScaleFit; else if (str::Eq(rangeList.At(i), L"compat")) advanced.asImage = true; else if (str::Parse(rangeList.At(i), L"%dx%$", &val) && 0 < val && val < 1000) devMode->dmCopies = (short)val; else if (str::Eq(rangeList.At(i), L"duplex") || str::Eq(rangeList.At(i), L"duplexlong")) devMode->dmDuplex = DMDUP_VERTICAL; else if (str::Eq(rangeList.At(i), L"duplexshort")) devMode->dmDuplex = DMDUP_HORIZONTAL; } if (ranges.Count() == 0) { PRINTPAGERANGE pr = { 1, pageCount }; ranges.Append(pr); } }
void NotificationWnd::UpdateProgress(int current, int total) { CrashIf(total <= 0); if (total <= 0) total = 1; progress = limitValue(100 * current / total, 0, 100); if (hasProgress && progressMsg) { ScopedMem<WCHAR> message(str::Format(progressMsg, current, total)); UpdateMessage(message); } }
static void ApplyPrintSettings(const WCHAR *settings, int pageCount, Vec<PRINTPAGERANGE>& ranges, Print_Advanced_Data& advanced) { WStrVec rangeList; if (settings) rangeList.Split(settings, L",", true); for (size_t i = 0; i < rangeList.Count(); i++) { PRINTPAGERANGE pr; if (str::Parse(rangeList.At(i), L"%d-%d%$", &pr.nFromPage, &pr.nToPage)) { pr.nFromPage = limitValue(pr.nFromPage, (DWORD)1, (DWORD)pageCount); pr.nToPage = limitValue(pr.nToPage, (DWORD)1, (DWORD)pageCount); ranges.Append(pr); } else if (str::Parse(rangeList.At(i), L"%d%$", &pr.nFromPage)) { pr.nFromPage = pr.nToPage = limitValue(pr.nFromPage, (DWORD)1, (DWORD)pageCount); ranges.Append(pr); } else if (str::Eq(rangeList.At(i), L"even")) advanced.range = PrintRangeEven; else if (str::Eq(rangeList.At(i), L"odd")) advanced.range = PrintRangeOdd; else if (str::Eq(rangeList.At(i), L"noscale")) advanced.scale = PrintScaleNone; else if (str::Eq(rangeList.At(i), L"shrink")) advanced.scale = PrintScaleShrink; else if (str::Eq(rangeList.At(i), L"fit")) advanced.scale = PrintScaleFit; else if (str::Eq(rangeList.At(i), L"compat")) advanced.asImage = true; } if (ranges.Count() == 0) { PRINTPAGERANGE pr = { 1, pageCount }; ranges.Append(pr); } }
static float GetZoomComboBoxValue(HWND hDlg, UINT idComboBox, bool forChm, float defaultZoom) { float newZoom = defaultZoom; int idx = ComboBox_GetCurSel(GetDlgItem(hDlg, idComboBox)); if (idx == -1) { ScopedMem<WCHAR> customZoom(win::GetText(GetDlgItem(hDlg, idComboBox))); float zoom = (float)_wtof(customZoom); if (zoom > 0) newZoom = limitValue(zoom, ZOOM_MIN, ZOOM_MAX); } else { if (forChm) idx += 7; if (0 != gItemZoom[idx]) newZoom = gItemZoom[idx]; } return newZoom; }
PaperFormat GetPaperFormat(SizeD size) { SizeD sizeP = size.dx < size.dy ? size : SizeD(size.dy, size.dx); // common ISO 216 formats (metric) if (limitValue(sizeP.dx, 8.26, 8.28) == sizeP.dx && limitValue(sizeP.dy, 11.68, 11.70) == sizeP.dy) return Paper_A4; if (limitValue(sizeP.dx, 11.68, 11.70) == sizeP.dx && limitValue(sizeP.dy, 16.53, 16.55) == sizeP.dy) return Paper_A3; if (limitValue(sizeP.dx, 5.82, 5.85) == sizeP.dx && limitValue(sizeP.dy, 8.26, 8.28) == sizeP.dy) return Paper_A5; // common US/ANSI formats (imperial) if (limitValue(sizeP.dx, 8.49, 8.51) == sizeP.dx && limitValue(sizeP.dy, 10.99, 11.01) == sizeP.dy) return Paper_Letter; if (limitValue(sizeP.dx, 8.49, 8.51) == sizeP.dx && limitValue(sizeP.dy, 13.99, 14.01) == sizeP.dy) return Paper_Legal; if (limitValue(sizeP.dx, 10.99, 11.01) == sizeP.dx && limitValue(sizeP.dy, 16.99, 17.01) == sizeP.dy) return Paper_Tabloid; if (limitValue(sizeP.dx, 5.49, 5.51) == sizeP.dx && limitValue(sizeP.dy, 8.49, 8.51) == sizeP.dy) return Paper_Statement; return Paper_Other; }
// format page size according to locale (e.g. "29.7 x 21.0 cm" or "11.69 x 8.27 in") // Caller needs to free the result static WCHAR *FormatPageSize(BaseEngine *engine, int pageNo, int rotation) { RectD mediabox = engine->PageMediabox(pageNo); SizeD size = engine->Transform(mediabox, pageNo, 1.0f / engine->GetFileDPI(), rotation).Size(); const WCHAR *formatName = L""; SizeD sizeP = size.dx < size.dy ? size : SizeD(size.dy, size.dx); // common ISO 216 formats (metric) if (limitValue(sizeP.dx, 8.26, 8.28) == sizeP.dx && limitValue(sizeP.dy, 11.68, 11.70) == sizeP.dy) formatName = L" (A4)"; else if (limitValue(sizeP.dx, 11.68, 11.70) == sizeP.dx && limitValue(sizeP.dy, 16.53, 16.55) == sizeP.dy) formatName = L" (A3)"; else if (limitValue(sizeP.dx, 5.82, 5.85) == sizeP.dx && limitValue(sizeP.dy, 8.26, 8.28) == sizeP.dy) formatName = L" (A5)"; // common US/ANSI formats (imperial) else if (limitValue(sizeP.dx, 8.49, 8.51) == sizeP.dx && limitValue(sizeP.dy, 10.99, 11.01) == sizeP.dy) formatName = L" (Letter)"; else if (limitValue(sizeP.dx, 8.49, 8.51) == sizeP.dx && limitValue(sizeP.dy, 13.99, 14.01) == sizeP.dy) formatName = L" (Legal)"; else if (limitValue(sizeP.dx, 10.99, 11.01) == sizeP.dx && limitValue(sizeP.dy, 16.99, 17.01) == sizeP.dy) formatName = L" (Tabloid)"; WCHAR unitSystem[2]; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, unitSystem, dimof(unitSystem)); bool isMetric = unitSystem[0] == '0'; double unitsPerInch = isMetric ? 2.54 : 1.0; const WCHAR *unit = isMetric ? L"cm" : L"in"; double width = size.dx * unitsPerInch; double height = size.dy * unitsPerInch; if (((int)(width * 100)) % 100 == 99) width += 0.01; if (((int)(height * 100)) % 100 == 99) height += 0.01; ScopedMem<WCHAR> strWidth(str::FormatFloatWithThousandSep(width)); ScopedMem<WCHAR> strHeight(str::FormatFloatWithThousandSep(height)); return str::Format(L"%s x %s %s%s", strWidth, strHeight, unit, formatName); }
void DrawStartPage(WindowInfo& win, HDC hdc, FileHistory& fileHistory, COLORREF colorRange[2]) { HPEN penBorder = CreatePen(PS_SOLID, DOCLIST_SEPARATOR_DY, WIN_COL_BLACK); HPEN penThumbBorder = CreatePen(PS_SOLID, DOCLIST_THUMBNAIL_BORDER_W, WIN_COL_BLACK); HPEN penLinkLine = CreatePen(PS_SOLID, 1, COL_BLUE_LINK); ScopedFont fontSumatraTxt(GetSimpleFont(hdc, L"MS Shell Dlg", 24)); ScopedFont fontLeftTxt(GetSimpleFont(hdc, L"MS Shell Dlg", 14)); HGDIOBJ origFont = SelectObject(hdc, fontSumatraTxt); /* Just to remember the orig font */ ClientRect rc(win.hwndCanvas); FillRect(hdc, &rc.ToRECT(), gBrushLogoBg); SelectObject(hdc, gBrushLogoBg); SelectObject(hdc, penBorder); bool isRtl = IsUIRightToLeft(); /* render title */ RectI titleBox = RectI(PointI(0, 0), CalcSumatraVersionSize(hdc)); titleBox.x = rc.dx - titleBox.dx - 3; DrawSumatraVersion(hdc, titleBox); PaintLine(hdc, RectI(0, titleBox.dy, rc.dx, 0)); /* render recent files list */ SelectObject(hdc, penThumbBorder); SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, WIN_COL_BLACK); rc.y += titleBox.dy; rc.dy -= titleBox.dy; FillRect(hdc, &rc.ToRECT(), gBrushAboutBg); rc.dy -= DOCLIST_BOTTOM_BOX_DY; Vec<DisplayState *> list; fileHistory.GetFrequencyOrder(list); int width = limitValue((rc.dx - DOCLIST_MARGIN_LEFT - DOCLIST_MARGIN_RIGHT + DOCLIST_MARGIN_BETWEEN_X) / (THUMBNAIL_DX + DOCLIST_MARGIN_BETWEEN_X), 1, DOCLIST_MAX_THUMBNAILS_X); int height = min((rc.dy - DOCLIST_MARGIN_TOP - DOCLIST_MARGIN_BOTTOM + DOCLIST_MARGIN_BETWEEN_Y) / (THUMBNAIL_DY + DOCLIST_MARGIN_BETWEEN_Y), FILE_HISTORY_MAX_FREQUENT / width); PointI offset(rc.x + DOCLIST_MARGIN_LEFT + (rc.dx - width * THUMBNAIL_DX - (width - 1) * DOCLIST_MARGIN_BETWEEN_X - DOCLIST_MARGIN_LEFT - DOCLIST_MARGIN_RIGHT) / 2, rc.y + DOCLIST_MARGIN_TOP); if (offset.x < ABOUT_INNER_PADDING) offset.x = ABOUT_INNER_PADDING; else if (list.Count() == 0) offset.x = DOCLIST_MARGIN_LEFT; SelectObject(hdc, fontSumatraTxt); SIZE txtSize; const WCHAR *txt = _TR("Frequently Read"); GetTextExtentPoint32(hdc, txt, (int)str::Len(txt), &txtSize); RectI headerRect(offset.x, rc.y + (DOCLIST_MARGIN_TOP - txtSize.cy) / 2, txtSize.cx, txtSize.cy); if (isRtl) headerRect.x = rc.dx - offset.x - headerRect.dx; DrawText(hdc, txt, -1, &headerRect.ToRECT(), (isRtl ? DT_RTLREADING : DT_LEFT) | DT_NOPREFIX); SelectObject(hdc, fontLeftTxt); SelectObject(hdc, GetStockBrush(NULL_BRUSH)); win.staticLinks.Reset(); for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { if (h * width + w >= (int)list.Count()) { // display the "Open a document" link right below the last row height = w > 0 ? h + 1 : h; break; } DisplayState *state = list.At(h * width + w); RectI page(offset.x + w * (int)(THUMBNAIL_DX + DOCLIST_MARGIN_BETWEEN_X * win.uiDPIFactor), offset.y + h * (int)(THUMBNAIL_DY + DOCLIST_MARGIN_BETWEEN_Y * win.uiDPIFactor), THUMBNAIL_DX, THUMBNAIL_DY); if (isRtl) page.x = rc.dx - page.x - page.dx; bool loadOk = true; if (!state->thumbnail) loadOk = LoadThumbnail(*state); if (loadOk && state->thumbnail) { SizeI thumbSize = state->thumbnail->Size(); if (thumbSize.dx != THUMBNAIL_DX || thumbSize.dy != THUMBNAIL_DY) { page.dy = thumbSize.dy * THUMBNAIL_DX / thumbSize.dx; page.y += THUMBNAIL_DY - page.dy; } HRGN clip = CreateRoundRectRgn(page.x, page.y, page.x + page.dx, page.y + page.dy, 10, 10); SelectClipRgn(hdc, clip); RenderedBitmap *clone = state->thumbnail->Clone(); UpdateBitmapColorRange(clone->GetBitmap(), colorRange); clone->StretchDIBits(hdc, page); SelectClipRgn(hdc, NULL); DeleteObject(clip); delete clone; } RoundRect(hdc, page.x, page.y, page.x + page.dx, page.y + page.dy, 10, 10); int iconSpace = (int)(20 * win.uiDPIFactor); RectI rect(page.x + iconSpace, page.y + page.dy + 3, page.dx - iconSpace, iconSpace); if (isRtl) rect.x -= iconSpace; DrawText(hdc, path::GetBaseName(state->filePath), -1, &rect.ToRECT(), DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX | (isRtl ? DT_RIGHT : DT_LEFT)); SHFILEINFO sfi; HIMAGELIST himl = (HIMAGELIST)SHGetFileInfo(state->filePath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES); ImageList_Draw(himl, sfi.iIcon, hdc, isRtl ? page.x + page.dx - (int)(16 * win.uiDPIFactor) : page.x, rect.y, ILD_TRANSPARENT); win.staticLinks.Append(StaticLinkInfo(rect.Union(page), state->filePath, state->filePath)); } } /* render bottom links */ rc.y += DOCLIST_MARGIN_TOP + height * THUMBNAIL_DY + (height - 1) * DOCLIST_MARGIN_BETWEEN_Y + DOCLIST_MARGIN_BOTTOM; rc.dy = DOCLIST_BOTTOM_BOX_DY; SetTextColor(hdc, COL_BLUE_LINK); SelectObject(hdc, penLinkLine); HIMAGELIST himl = (HIMAGELIST)SendMessage(win.hwndToolbar, TB_GETIMAGELIST, 0, 0); RectI rectIcon(offset.x, rc.y, 0, 0); ImageList_GetIconSize(himl, &rectIcon.dx, &rectIcon.dy); rectIcon.y += (rc.dy - rectIcon.dy) / 2; if (isRtl) rectIcon.x = rc.dx - offset.x - rectIcon.dx; ImageList_Draw(himl, 0 /* index of Open icon */, hdc, rectIcon.x, rectIcon.y, ILD_NORMAL); txt = _TR("Open a document..."); GetTextExtentPoint32(hdc, txt, (int)str::Len(txt), &txtSize); RectI rect(offset.x + rectIcon.dx + 3, rc.y + (rc.dy - txtSize.cy) / 2, txtSize.cx, txtSize.cy); if (isRtl) rect.x = rectIcon.x - rect.dx - 3; DrawText(hdc, txt, -1, &rect.ToRECT(), isRtl ? DT_RTLREADING : DT_LEFT); PaintLine(hdc, RectI(rect.x, rect.y + rect.dy, rect.dx, 0)); // make the click target larger rect = rect.Union(rectIcon); rect.Inflate(10, 10); win.staticLinks.Append(StaticLinkInfo(rect, SLINK_OPEN_FILE)); rect = DrawBottomRightLink(win.hwndCanvas, hdc, _TR("Hide frequently read")); win.staticLinks.Append(StaticLinkInfo(rect, SLINK_LIST_HIDE)); SelectObject(hdc, origFont); DeleteObject(penBorder); DeleteObject(penThumbBorder); DeleteObject(penLinkLine); }