cdd_conversion_win.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/service/cloud_print/cdd_conversion_win.h"
6
7#include "components/cloud_devices/printer_description.h"
8#include "printing/backend/print_backend.h"
9#include "printing/backend/win_helper.h"
10
11namespace cloud_print {
12
13bool IsValidCjt(const std::string& print_ticket_data) {
14  cloud_devices::CloudDeviceDescription description;
15  return description.InitFromString(print_ticket_data);
16}
17
18scoped_ptr<DEVMODE, base::FreeDeleter> CjtToDevMode(
19    const base::string16& printer_name,
20    const std::string& print_ticket) {
21  scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode;
22
23  cloud_devices::CloudDeviceDescription description;
24  if (!description.InitFromString(print_ticket))
25    return dev_mode.Pass();
26
27  using namespace cloud_devices::printer;
28  printing::ScopedPrinterHandle printer;
29  if (!printer.OpenPrinter(printer_name.c_str()))
30    return dev_mode.Pass();
31
32  {
33    ColorTicketItem color;
34    if (color.LoadFrom(description)) {
35      bool is_color = color.value().type == STANDARD_COLOR;
36      dev_mode = CreateDevModeWithColor(printer, printer_name, is_color);
37    } else {
38      dev_mode = printing::CreateDevMode(printer, NULL);
39    }
40  }
41
42  if (!dev_mode)
43    return dev_mode.Pass();
44
45  ColorTicketItem color;
46  DuplexTicketItem duplex;
47  OrientationTicketItem orientation;
48  MarginsTicketItem margins;
49  DpiTicketItem dpi;
50  FitToPageTicketItem fit_to_page;
51  MediaTicketItem media;
52  CopiesTicketItem copies;
53  PageRangeTicketItem page_range;
54  CollateTicketItem collate;
55  ReverseTicketItem reverse;
56
57  if (orientation.LoadFrom(description)) {
58    dev_mode->dmFields |= DM_ORIENTATION;
59    if (orientation.value() == LANDSCAPE) {
60      dev_mode->dmOrientation = DMORIENT_LANDSCAPE;
61    } else {
62      dev_mode->dmOrientation = DMORIENT_PORTRAIT;
63    }
64  }
65
66  if (color.LoadFrom(description)) {
67    dev_mode->dmFields |= DM_COLOR;
68    if (color.value().type == STANDARD_MONOCHROME) {
69      dev_mode->dmColor = DMCOLOR_MONOCHROME;
70    } else if (color.value().type == STANDARD_COLOR) {
71      dev_mode->dmColor = DMCOLOR_COLOR;
72    } else {
73      NOTREACHED();
74    }
75  }
76
77  if (duplex.LoadFrom(description)) {
78    dev_mode->dmFields |= DM_DUPLEX;
79    if (duplex.value() == NO_DUPLEX) {
80      dev_mode->dmDuplex = DMDUP_SIMPLEX;
81    } else if (duplex.value() == LONG_EDGE) {
82      dev_mode->dmDuplex = DMDUP_VERTICAL;
83    } else if (duplex.value() == SHORT_EDGE) {
84      dev_mode->dmDuplex = DMDUP_HORIZONTAL;
85    } else {
86      NOTREACHED();
87    }
88  }
89
90  if (copies.LoadFrom(description)) {
91    dev_mode->dmFields |= DM_COPIES;
92    dev_mode->dmCopies = copies.value();
93  }
94
95  if (dpi.LoadFrom(description)) {
96    if (dpi.value().horizontal > 0) {
97      dev_mode->dmFields |= DM_PRINTQUALITY;
98      dev_mode->dmPrintQuality = dpi.value().horizontal;
99    }
100    if (dpi.value().vertical > 0) {
101      dev_mode->dmFields |= DM_YRESOLUTION;
102      dev_mode->dmYResolution = dpi.value().vertical;
103    }
104  }
105
106  if (collate.LoadFrom(description)) {
107    dev_mode->dmFields |= DM_COLLATE;
108    dev_mode->dmCollate = (collate.value() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE);
109  }
110
111  if (media.LoadFrom(description)) {
112    static const size_t kFromUm = 100;  // Windows uses 0.1mm.
113    int width = media.value().width_um / kFromUm;
114    int height = media.value().height_um / kFromUm;
115    if (width > 0) {
116      dev_mode->dmFields |= DM_PAPERWIDTH;
117      dev_mode->dmPaperWidth = width;
118    }
119    if (height > 0) {
120      dev_mode->dmFields |= DM_PAPERLENGTH;
121      dev_mode->dmPaperLength = height;
122    }
123  }
124
125  return printing::CreateDevMode(printer, dev_mode.get());
126}
127
128std::string CapabilitiesToCdd(
129    const printing::PrinterSemanticCapsAndDefaults& semantic_info) {
130  using namespace cloud_devices::printer;
131  cloud_devices::CloudDeviceDescription description;
132
133  ContentTypesCapability content_types;
134  content_types.AddOption("application/pdf");
135  content_types.SaveTo(&description);
136
137  ColorCapability color;
138  if (semantic_info.color_default || semantic_info.color_changeable) {
139    color.AddDefaultOption(Color(STANDARD_COLOR), semantic_info.color_default);
140  }
141
142  if (!semantic_info.color_default || semantic_info.color_changeable) {
143    color.AddDefaultOption(Color(STANDARD_MONOCHROME),
144                           !semantic_info.color_default);
145  }
146  color.SaveTo(&description);
147
148  if (semantic_info.duplex_capable) {
149    DuplexCapability duplex;
150    duplex.AddDefaultOption(
151        NO_DUPLEX, semantic_info.duplex_default == printing::SIMPLEX);
152    duplex.AddDefaultOption(
153        LONG_EDGE, semantic_info.duplex_default == printing::LONG_EDGE);
154    duplex.AddDefaultOption(
155        SHORT_EDGE, semantic_info.duplex_default == printing::SHORT_EDGE);
156    duplex.SaveTo(&description);
157  }
158
159  if (!semantic_info.papers.empty()) {
160    Media default_media(semantic_info.default_paper.name,
161                        semantic_info.default_paper.size_um.width(),
162                        semantic_info.default_paper.size_um.height());
163    default_media.MatchBySize();
164
165    MediaCapability media;
166    bool is_default_set = false;
167    for (size_t i = 0; i < semantic_info.papers.size(); ++i) {
168      gfx::Size paper_size = semantic_info.papers[i].size_um;
169      if (paper_size.width() > paper_size.height())
170        paper_size.SetSize(paper_size.height(), paper_size.width());
171      Media new_media(semantic_info.papers[i].name, paper_size.width(),
172                      paper_size.height());
173      new_media.MatchBySize();
174      if (new_media.IsValid() && !media.Contains(new_media)) {
175        if (!default_media.IsValid())
176          default_media = new_media;
177        media.AddDefaultOption(new_media, new_media == default_media);
178        is_default_set = is_default_set || (new_media == default_media);
179      }
180    }
181    if (!is_default_set && default_media.IsValid())
182      media.AddDefaultOption(default_media, true);
183
184    if (media.IsValid()) {
185      media.SaveTo(&description);
186    } else {
187      NOTREACHED();
188    }
189  }
190
191  if (semantic_info.collate_capable) {
192    CollateCapability collate;
193    collate.set_default_value(semantic_info.collate_default);
194    collate.SaveTo(&description);
195  }
196
197  if (semantic_info.copies_capable) {
198    CopiesCapability copies;
199    copies.SaveTo(&description);
200  }
201
202  if (!semantic_info.dpis.empty()) {
203    DpiCapability dpi;
204    Dpi default_dpi(semantic_info.default_dpi.width(),
205                    semantic_info.default_dpi.height());
206    bool is_default_set = false;
207    for (size_t i = 0; i < semantic_info.dpis.size(); ++i) {
208      Dpi new_dpi(semantic_info.dpis[i].width(),
209                  semantic_info.dpis[i].height());
210      if (new_dpi.IsValid() && !dpi.Contains(new_dpi)) {
211        if (!default_dpi.IsValid())
212          default_dpi = new_dpi;
213        dpi.AddDefaultOption(new_dpi, new_dpi == default_dpi);
214        is_default_set = is_default_set || (new_dpi == default_dpi);
215      }
216    }
217    if (!is_default_set && default_dpi.IsValid())
218      dpi.AddDefaultOption(default_dpi, true);
219    if (dpi.IsValid()) {
220      dpi.SaveTo(&description);
221    } else {
222      NOTREACHED();
223    }
224  }
225
226  OrientationCapability orientation;
227  orientation.AddDefaultOption(PORTRAIT, true);
228  orientation.AddOption(LANDSCAPE);
229  orientation.AddOption(AUTO_ORIENTATION);
230  orientation.SaveTo(&description);
231
232  return description.ToString();
233}
234
235}  // namespace cloud_print
236