Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: core/fpdfdoc/doc_utils.cpp

Issue 1862123003: Rename both As{Byte,Wide}StringC() helpers to AsStringC(). (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Rebase, fix new usage. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fpdfdoc/doc_tagged.cpp ('k') | core/fxcrt/fx_basic_bstring.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "core/fpdfapi/fpdf_font/include/cpdf_font.h" 10 #include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 } 75 }
76 } 76 }
77 pLevel = pLevel->GetDictBy("Parent"); 77 pLevel = pLevel->GetDictBy("Parent");
78 } 78 }
79 return full_name; 79 return full_name;
80 } 80 }
81 FX_BOOL CPDF_DefaultAppearance::HasFont() { 81 FX_BOOL CPDF_DefaultAppearance::HasFont() {
82 if (m_csDA.IsEmpty()) { 82 if (m_csDA.IsEmpty()) {
83 return FALSE; 83 return FALSE;
84 } 84 }
85 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 85 CPDF_SimpleParser syntax(m_csDA.AsStringC());
86 return syntax.FindTagParamFromStart("Tf", 2); 86 return syntax.FindTagParamFromStart("Tf", 2);
87 } 87 }
88 CFX_ByteString CPDF_DefaultAppearance::GetFontString() { 88 CFX_ByteString CPDF_DefaultAppearance::GetFontString() {
89 CFX_ByteString csFont; 89 CFX_ByteString csFont;
90 if (m_csDA.IsEmpty()) { 90 if (m_csDA.IsEmpty()) {
91 return csFont; 91 return csFont;
92 } 92 }
93 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 93 CPDF_SimpleParser syntax(m_csDA.AsStringC());
94 if (syntax.FindTagParamFromStart("Tf", 2)) { 94 if (syntax.FindTagParamFromStart("Tf", 2)) {
95 csFont += (CFX_ByteString)syntax.GetWord(); 95 csFont += (CFX_ByteString)syntax.GetWord();
96 csFont += " "; 96 csFont += " ";
97 csFont += (CFX_ByteString)syntax.GetWord(); 97 csFont += (CFX_ByteString)syntax.GetWord();
98 csFont += " "; 98 csFont += " ";
99 csFont += (CFX_ByteString)syntax.GetWord(); 99 csFont += (CFX_ByteString)syntax.GetWord();
100 } 100 }
101 return csFont; 101 return csFont;
102 } 102 }
103 void CPDF_DefaultAppearance::GetFont(CFX_ByteString& csFontNameTag, 103 void CPDF_DefaultAppearance::GetFont(CFX_ByteString& csFontNameTag,
104 FX_FLOAT& fFontSize) { 104 FX_FLOAT& fFontSize) {
105 csFontNameTag = ""; 105 csFontNameTag = "";
106 fFontSize = 0; 106 fFontSize = 0;
107 if (m_csDA.IsEmpty()) { 107 if (m_csDA.IsEmpty()) {
108 return; 108 return;
109 } 109 }
110 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 110 CPDF_SimpleParser syntax(m_csDA.AsStringC());
111 if (syntax.FindTagParamFromStart("Tf", 2)) { 111 if (syntax.FindTagParamFromStart("Tf", 2)) {
112 csFontNameTag = CFX_ByteString(syntax.GetWord()); 112 csFontNameTag = CFX_ByteString(syntax.GetWord());
113 csFontNameTag.Delete(0, 1); 113 csFontNameTag.Delete(0, 1);
114 fFontSize = FX_atof(syntax.GetWord()); 114 fFontSize = FX_atof(syntax.GetWord());
115 } 115 }
116 csFontNameTag = PDF_NameDecode(csFontNameTag); 116 csFontNameTag = PDF_NameDecode(csFontNameTag);
117 } 117 }
118 FX_BOOL CPDF_DefaultAppearance::HasColor(FX_BOOL bStrokingOperation) { 118 FX_BOOL CPDF_DefaultAppearance::HasColor(FX_BOOL bStrokingOperation) {
119 if (m_csDA.IsEmpty()) { 119 if (m_csDA.IsEmpty()) {
120 return FALSE; 120 return FALSE;
121 } 121 }
122 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 122 CPDF_SimpleParser syntax(m_csDA.AsStringC());
123 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) { 123 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) {
124 return TRUE; 124 return TRUE;
125 } 125 }
126 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) { 126 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) {
127 return TRUE; 127 return TRUE;
128 } 128 }
129 return syntax.FindTagParamFromStart(bStrokingOperation ? "K" : "k", 4); 129 return syntax.FindTagParamFromStart(bStrokingOperation ? "K" : "k", 4);
130 } 130 }
131 CFX_ByteString CPDF_DefaultAppearance::GetColorString( 131 CFX_ByteString CPDF_DefaultAppearance::GetColorString(
132 FX_BOOL bStrokingOperation) { 132 FX_BOOL bStrokingOperation) {
133 CFX_ByteString csColor; 133 CFX_ByteString csColor;
134 if (m_csDA.IsEmpty()) { 134 if (m_csDA.IsEmpty()) {
135 return csColor; 135 return csColor;
136 } 136 }
137 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 137 CPDF_SimpleParser syntax(m_csDA.AsStringC());
138 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) { 138 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) {
139 csColor += (CFX_ByteString)syntax.GetWord(); 139 csColor += (CFX_ByteString)syntax.GetWord();
140 csColor += " "; 140 csColor += " ";
141 csColor += (CFX_ByteString)syntax.GetWord(); 141 csColor += (CFX_ByteString)syntax.GetWord();
142 return csColor; 142 return csColor;
143 } 143 }
144 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) { 144 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) {
145 csColor += (CFX_ByteString)syntax.GetWord(); 145 csColor += (CFX_ByteString)syntax.GetWord();
146 csColor += " "; 146 csColor += " ";
147 csColor += (CFX_ByteString)syntax.GetWord(); 147 csColor += (CFX_ByteString)syntax.GetWord();
(...skipping 19 matching lines...) Expand all
167 void CPDF_DefaultAppearance::GetColor(int& iColorType, 167 void CPDF_DefaultAppearance::GetColor(int& iColorType,
168 FX_FLOAT fc[4], 168 FX_FLOAT fc[4],
169 FX_BOOL bStrokingOperation) { 169 FX_BOOL bStrokingOperation) {
170 iColorType = COLORTYPE_TRANSPARENT; 170 iColorType = COLORTYPE_TRANSPARENT;
171 for (int c = 0; c < 4; c++) { 171 for (int c = 0; c < 4; c++) {
172 fc[c] = 0; 172 fc[c] = 0;
173 } 173 }
174 if (m_csDA.IsEmpty()) { 174 if (m_csDA.IsEmpty()) {
175 return; 175 return;
176 } 176 }
177 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 177 CPDF_SimpleParser syntax(m_csDA.AsStringC());
178 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) { 178 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) {
179 iColorType = COLORTYPE_GRAY; 179 iColorType = COLORTYPE_GRAY;
180 fc[0] = FX_atof(syntax.GetWord()); 180 fc[0] = FX_atof(syntax.GetWord());
181 return; 181 return;
182 } 182 }
183 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) { 183 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) {
184 iColorType = COLORTYPE_RGB; 184 iColorType = COLORTYPE_RGB;
185 fc[0] = FX_atof(syntax.GetWord()); 185 fc[0] = FX_atof(syntax.GetWord());
186 fc[1] = FX_atof(syntax.GetWord()); 186 fc[1] = FX_atof(syntax.GetWord());
187 fc[2] = FX_atof(syntax.GetWord()); 187 fc[2] = FX_atof(syntax.GetWord());
188 return; 188 return;
189 } 189 }
190 if (syntax.FindTagParamFromStart(bStrokingOperation ? "K" : "k", 4)) { 190 if (syntax.FindTagParamFromStart(bStrokingOperation ? "K" : "k", 4)) {
191 iColorType = COLORTYPE_CMYK; 191 iColorType = COLORTYPE_CMYK;
192 fc[0] = FX_atof(syntax.GetWord()); 192 fc[0] = FX_atof(syntax.GetWord());
193 fc[1] = FX_atof(syntax.GetWord()); 193 fc[1] = FX_atof(syntax.GetWord());
194 fc[2] = FX_atof(syntax.GetWord()); 194 fc[2] = FX_atof(syntax.GetWord());
195 fc[3] = FX_atof(syntax.GetWord()); 195 fc[3] = FX_atof(syntax.GetWord());
196 } 196 }
197 } 197 }
198 void CPDF_DefaultAppearance::GetColor(FX_ARGB& color, 198 void CPDF_DefaultAppearance::GetColor(FX_ARGB& color,
199 int& iColorType, 199 int& iColorType,
200 FX_BOOL bStrokingOperation) { 200 FX_BOOL bStrokingOperation) {
201 color = 0; 201 color = 0;
202 iColorType = COLORTYPE_TRANSPARENT; 202 iColorType = COLORTYPE_TRANSPARENT;
203 if (m_csDA.IsEmpty()) { 203 if (m_csDA.IsEmpty()) {
204 return; 204 return;
205 } 205 }
206 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 206 CPDF_SimpleParser syntax(m_csDA.AsStringC());
207 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) { 207 if (syntax.FindTagParamFromStart(bStrokingOperation ? "G" : "g", 1)) {
208 iColorType = COLORTYPE_GRAY; 208 iColorType = COLORTYPE_GRAY;
209 FX_FLOAT g = FX_atof(syntax.GetWord()) * 255 + 0.5f; 209 FX_FLOAT g = FX_atof(syntax.GetWord()) * 255 + 0.5f;
210 color = ArgbEncode(255, (int)g, (int)g, (int)g); 210 color = ArgbEncode(255, (int)g, (int)g, (int)g);
211 return; 211 return;
212 } 212 }
213 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) { 213 if (syntax.FindTagParamFromStart(bStrokingOperation ? "RG" : "rg", 3)) {
214 iColorType = COLORTYPE_RGB; 214 iColorType = COLORTYPE_RGB;
215 FX_FLOAT r = FX_atof(syntax.GetWord()) * 255 + 0.5f; 215 FX_FLOAT r = FX_atof(syntax.GetWord()) * 255 + 0.5f;
216 FX_FLOAT g = FX_atof(syntax.GetWord()) * 255 + 0.5f; 216 FX_FLOAT g = FX_atof(syntax.GetWord()) * 255 + 0.5f;
(...skipping 11 matching lines...) Expand all
228 FX_FLOAT g = 1.0f - std::min(1.0f, m + k); 228 FX_FLOAT g = 1.0f - std::min(1.0f, m + k);
229 FX_FLOAT b = 1.0f - std::min(1.0f, y + k); 229 FX_FLOAT b = 1.0f - std::min(1.0f, y + k);
230 color = ArgbEncode(255, (int)(r * 255 + 0.5f), (int)(g * 255 + 0.5f), 230 color = ArgbEncode(255, (int)(r * 255 + 0.5f), (int)(g * 255 + 0.5f),
231 (int)(b * 255 + 0.5f)); 231 (int)(b * 255 + 0.5f));
232 } 232 }
233 } 233 }
234 FX_BOOL CPDF_DefaultAppearance::HasTextMatrix() { 234 FX_BOOL CPDF_DefaultAppearance::HasTextMatrix() {
235 if (m_csDA.IsEmpty()) { 235 if (m_csDA.IsEmpty()) {
236 return FALSE; 236 return FALSE;
237 } 237 }
238 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 238 CPDF_SimpleParser syntax(m_csDA.AsStringC());
239 return syntax.FindTagParamFromStart("Tm", 6); 239 return syntax.FindTagParamFromStart("Tm", 6);
240 } 240 }
241 CFX_ByteString CPDF_DefaultAppearance::GetTextMatrixString() { 241 CFX_ByteString CPDF_DefaultAppearance::GetTextMatrixString() {
242 CFX_ByteString csTM; 242 CFX_ByteString csTM;
243 if (m_csDA.IsEmpty()) { 243 if (m_csDA.IsEmpty()) {
244 return csTM; 244 return csTM;
245 } 245 }
246 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 246 CPDF_SimpleParser syntax(m_csDA.AsStringC());
247 if (syntax.FindTagParamFromStart("Tm", 6)) { 247 if (syntax.FindTagParamFromStart("Tm", 6)) {
248 for (int i = 0; i < 6; i++) { 248 for (int i = 0; i < 6; i++) {
249 csTM += (CFX_ByteString)syntax.GetWord(); 249 csTM += (CFX_ByteString)syntax.GetWord();
250 csTM += " "; 250 csTM += " ";
251 } 251 }
252 csTM += (CFX_ByteString)syntax.GetWord(); 252 csTM += (CFX_ByteString)syntax.GetWord();
253 } 253 }
254 return csTM; 254 return csTM;
255 } 255 }
256 CFX_Matrix CPDF_DefaultAppearance::GetTextMatrix() { 256 CFX_Matrix CPDF_DefaultAppearance::GetTextMatrix() {
257 CFX_Matrix tm; 257 CFX_Matrix tm;
258 if (m_csDA.IsEmpty()) { 258 if (m_csDA.IsEmpty()) {
259 return tm; 259 return tm;
260 } 260 }
261 CPDF_SimpleParser syntax(m_csDA.AsByteStringC()); 261 CPDF_SimpleParser syntax(m_csDA.AsStringC());
262 if (syntax.FindTagParamFromStart("Tm", 6)) { 262 if (syntax.FindTagParamFromStart("Tm", 6)) {
263 FX_FLOAT f[6]; 263 FX_FLOAT f[6];
264 for (int i = 0; i < 6; i++) { 264 for (int i = 0; i < 6; i++) {
265 f[i] = FX_atof(syntax.GetWord()); 265 f[i] = FX_atof(syntax.GetWord());
266 } 266 }
267 tm.Set(f[0], f[1], f[2], f[3], f[4], f[5]); 267 tm.Set(f[0], f[1], f[2], f[3], f[4], f[5]);
268 } 268 }
269 return tm; 269 return tm;
270 } 270 }
271 void InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) { 271 void InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) {
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 return NULL; 380 return NULL;
381 } 381 }
382 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); 382 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR");
383 if (!pDR) { 383 if (!pDR) {
384 return NULL; 384 return NULL;
385 } 385 }
386 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); 386 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font");
387 if (!pFonts) { 387 if (!pFonts) {
388 return NULL; 388 return NULL;
389 } 389 }
390 CPDF_Dictionary* pElement = pFonts->GetDictBy(csAlias.AsByteStringC()); 390 CPDF_Dictionary* pElement = pFonts->GetDictBy(csAlias.AsStringC());
391 if (!pElement) { 391 if (!pElement) {
392 return NULL; 392 return NULL;
393 } 393 }
394 if (pElement->GetStringBy("Type") == "Font") { 394 if (pElement->GetStringBy("Type") == "Font") {
395 return pDocument->LoadFont(pElement); 395 return pDocument->LoadFont(pElement);
396 } 396 }
397 return NULL; 397 return NULL;
398 } 398 }
399 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, 399 CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict,
400 CPDF_Document* pDocument, 400 CPDF_Document* pDocument,
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 if (!pFonts) { 599 if (!pFonts) {
600 pFonts = new CPDF_Dictionary; 600 pFonts = new CPDF_Dictionary;
601 pDR->SetAt("Font", pFonts); 601 pDR->SetAt("Font", pFonts);
602 } 602 }
603 if (csNameTag.IsEmpty()) { 603 if (csNameTag.IsEmpty()) {
604 csNameTag = pFont->GetBaseFont(); 604 csNameTag = pFont->GetBaseFont();
605 } 605 }
606 csNameTag.Remove(' '); 606 csNameTag.Remove(' ');
607 csNameTag = 607 csNameTag =
608 CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, csNameTag); 608 CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, csNameTag);
609 pFonts->SetAtReference(csNameTag.AsByteStringC(), pDocument, 609 pFonts->SetAtReference(csNameTag.AsStringC(), pDocument,
610 pFont->GetFontDict()); 610 pFont->GetFontDict());
611 } 611 }
612 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, 612 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict,
613 CPDF_Document* pDocument, 613 CPDF_Document* pDocument,
614 uint8_t charSet, 614 uint8_t charSet,
615 CFX_ByteString& csNameTag) { 615 CFX_ByteString& csNameTag) {
616 if (!pFormDict) { 616 if (!pFormDict) {
617 InitInterFormDict(pFormDict, pDocument); 617 InitInterFormDict(pFormDict, pDocument);
618 } 618 }
619 CFX_ByteString csTemp; 619 CFX_ByteString csTemp;
(...skipping 24 matching lines...) Expand all
644 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont) { 644 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont) {
645 if (!pFormDict || !pFont) { 645 if (!pFormDict || !pFont) {
646 return; 646 return;
647 } 647 }
648 CFX_ByteString csTag; 648 CFX_ByteString csTag;
649 if (!FindInterFormFont(pFormDict, pFont, csTag)) { 649 if (!FindInterFormFont(pFormDict, pFont, csTag)) {
650 return; 650 return;
651 } 651 }
652 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); 652 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR");
653 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); 653 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font");
654 pFonts->RemoveAt(csTag.AsByteStringC()); 654 pFonts->RemoveAt(csTag.AsStringC());
655 } 655 }
656 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag) { 656 void RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag) {
657 if (!pFormDict || csNameTag.IsEmpty()) { 657 if (!pFormDict || csNameTag.IsEmpty()) {
658 return; 658 return;
659 } 659 }
660 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR"); 660 CPDF_Dictionary* pDR = pFormDict->GetDictBy("DR");
661 if (!pDR) { 661 if (!pDR) {
662 return; 662 return;
663 } 663 }
664 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font"); 664 CPDF_Dictionary* pFonts = pDR->GetDictBy("Font");
665 if (!pFonts) { 665 if (!pFonts) {
666 return; 666 return;
667 } 667 }
668 pFonts->RemoveAt(csNameTag.AsByteStringC()); 668 pFonts->RemoveAt(csNameTag.AsStringC());
669 } 669 }
670 670
671 CPDF_Font* GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, 671 CPDF_Font* GetDefaultInterFormFont(CPDF_Dictionary* pFormDict,
672 CPDF_Document* pDocument) { 672 CPDF_Document* pDocument) {
673 if (!pFormDict) { 673 if (!pFormDict) {
674 return NULL; 674 return NULL;
675 } 675 }
676 CPDF_DefaultAppearance cDA(pFormDict->GetStringBy("DA")); 676 CPDF_DefaultAppearance cDA(pFormDict->GetStringBy("DA"));
677 CFX_ByteString csFontNameTag; 677 CFX_ByteString csFontNameTag;
678 FX_FLOAT fFontSize; 678 FX_FLOAT fFontSize;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 CPDF_Object* pAttr = pFieldDict->GetDirectObjectBy(name); 747 CPDF_Object* pAttr = pFieldDict->GetDirectObjectBy(name);
748 if (pAttr) { 748 if (pAttr) {
749 return pAttr; 749 return pAttr;
750 } 750 }
751 CPDF_Dictionary* pParent = pFieldDict->GetDictBy("Parent"); 751 CPDF_Dictionary* pParent = pFieldDict->GetDictBy("Parent");
752 if (!pParent) { 752 if (!pParent) {
753 return NULL; 753 return NULL;
754 } 754 }
755 return FPDF_GetFieldAttr(pParent, name, nLevel + 1); 755 return FPDF_GetFieldAttr(pParent, name, nLevel + 1);
756 } 756 }
OLDNEW
« no previous file with comments | « core/fpdfdoc/doc_tagged.cpp ('k') | core/fxcrt/fx_basic_bstring.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698