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

Side by Side Diff: core/src/fxge/ge/fx_ge_linux.cpp

Issue 453133004: clang-format all code (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 6 years, 4 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
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 "../../../include/fxge/fx_ge.h" 7 #include "../../../include/fxge/fx_ge.h"
8 #include "../agg/include/fx_agg_driver.h" 8 #include "../agg/include/fx_agg_driver.h"
9 #include "text_int.h" 9 #include "text_int.h"
10 #if !defined(_FPDFAPI_MINI_) && _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ 10 #if !defined(_FPDFAPI_MINI_) && _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
11 #if (_FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ && (!defined(_FPDFAPI_MINI_))) 11 #if (_FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ && (!defined(_FPDFAPI_MINI_)))
12 void CFX_AggDeviceDriver::InitPlatform() 12 void CFX_AggDeviceDriver::InitPlatform() {
13 { 13 }
14 } 14 void CFX_AggDeviceDriver::DestroyPlatform() {
15 void CFX_AggDeviceDriver::DestroyPlatform() 15 }
16 { 16 void CFX_FaceCache::InitPlatform() {
17 } 17 }
18 void CFX_FaceCache::InitPlatform() 18 FX_BOOL CFX_AggDeviceDriver::DrawDeviceText(
19 { 19 int nChars,
20 } 20 const FXTEXT_CHARPOS* pCharPos,
21 FX_BOOL CFX_AggDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pC harPos, CFX_Font* pFont, 21 CFX_Font* pFont,
22 CFX_FontCache* pCache, const CFX_AffineMatrix* pObject2Device, 22 CFX_FontCache* pCache,
23 FX_FLOAT font_size, FX_DWORD argb) 23 const CFX_AffineMatrix* pObject2Device,
24 { 24 FX_FLOAT font_size,
25 return FALSE; 25 FX_DWORD argb) {
26 } 26 return FALSE;
27 CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph_Nativetext(CFX_Font* pFont, FX_DWORD glyph_index, const CFX_AffineMatrix* pMatrix, 27 }
28 int dest_width, int anti_alias) 28 CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph_Nativetext(
29 { 29 CFX_Font* pFont,
30 return NULL; 30 FX_DWORD glyph_index,
31 } 31 const CFX_AffineMatrix* pMatrix,
32 void CFX_Font::ReleasePlatformResource() 32 int dest_width,
33 { 33 int anti_alias) {
34 return NULL;
35 }
36 void CFX_Font::ReleasePlatformResource() {
34 } 37 }
35 #endif 38 #endif
36 static const struct { 39 static const struct {
37 FX_LPCSTR» m_pName; 40 FX_LPCSTR m_pName;
38 FX_LPCSTR» m_pSubstName; 41 FX_LPCSTR m_pSubstName;
39 } 42 } Base14Substs[] = {
40 Base14Substs[] = { 43 { "Courier", "Courier New" },
41 {"Courier", "Courier New"}, 44 { "Courier-Bold", "Courier New Bold" },
42 {"Courier-Bold", "Courier New Bold"}, 45 { "Courier-BoldOblique", "Courier New Bold Italic" },
43 {"Courier-BoldOblique", "Courier New Bold Italic"}, 46 { "Courier-Oblique", "Courier New Italic" },
44 {"Courier-Oblique", "Courier New Italic"}, 47 { "Helvetica", "Arial" },
45 {"Helvetica", "Arial"}, 48 { "Helvetica-Bold", "Arial Bold" },
46 {"Helvetica-Bold", "Arial Bold"}, 49 { "Helvetica-BoldOblique", "Arial Bold Italic" },
47 {"Helvetica-BoldOblique", "Arial Bold Italic"}, 50 { "Helvetica-Oblique", "Arial Italic" },
48 {"Helvetica-Oblique", "Arial Italic"}, 51 { "Times-Roman", "Times New Roman" },
49 {"Times-Roman", "Times New Roman"}, 52 { "Times-Bold", "Times New Roman Bold" },
50 {"Times-Bold", "Times New Roman Bold"}, 53 { "Times-BoldItalic", "Times New Roman Bold Italic" },
51 {"Times-BoldItalic", "Times New Roman Bold Italic"}, 54 { "Times-Italic", "Times New Roman Italic" },
52 {"Times-Italic", "Times New Roman Italic"}, 55 };
53 }; 56 class CFX_LinuxFontInfo : public CFX_FolderFontInfo {
54 class CFX_LinuxFontInfo : public CFX_FolderFontInfo 57 public:
55 { 58 virtual void* MapFont(int weight,
56 public: 59 FX_BOOL bItalic,
57 virtual void*» » MapFont(int weight, FX_BOOL bItalic, int charset , int pitch_family, FX_LPCSTR family, FX_BOOL& bExact); 60 int charset,
58 FX_BOOL» » » » ParseFontCfg(); 61 int pitch_family,
59 void*» » » » FindFont(int weight, FX_BOOL bItalic, in t charset, int pitch_family, FX_LPCSTR family, FX_BOOL bMatchName); 62 FX_LPCSTR family,
60 }; 63 FX_BOOL& bExact);
61 #define LINUX_GPNAMESIZE» 6 64 FX_BOOL ParseFontCfg();
65 void* FindFont(int weight,
66 FX_BOOL bItalic,
67 int charset,
68 int pitch_family,
69 FX_LPCSTR family,
70 FX_BOOL bMatchName);
71 };
72 #define LINUX_GPNAMESIZE 6
62 static const struct { 73 static const struct {
63 FX_LPCSTR NameArr[LINUX_GPNAMESIZE]; 74 FX_LPCSTR NameArr[LINUX_GPNAMESIZE];
64 } 75 } LinuxGpFontList[] = {
65 LinuxGpFontList[] = { 76 { { "TakaoPGothic",
66 {{"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic", " VL Gothic regular"}}, 77 "VL PGothic",
67 {{"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", NULL, "VL Gothic regular"}}, 78 "IPAPGothic",
68 {{"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", NULL, "VL Gothi c regular"}}, 79 "VL Gothic",
69 {{"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", NULL, "VL Gothic regular"}}, 80 "Kochi Gothic",
70 }; 81 "VL Gothic regular" } },
82 { { "TakaoGothic",
83 "VL Gothic",
84 "IPAGothic",
85 "Kochi Gothic",
86 NULL,
87 "VL Gothic regular" } },
88 { { "TakaoPMincho",
89 "IPAPMincho",
90 "VL Gothic",
91 "Kochi Mincho",
92 NULL,
93 "VL Gothic regular" } },
94 { { "TakaoMincho",
95 "IPAMincho",
96 "VL Gothic",
97 "Kochi Mincho",
98 NULL,
99 "VL Gothic regular" } },
100 };
71 static const FX_LPCSTR g_LinuxGbFontList[] = { 101 static const FX_LPCSTR g_LinuxGbFontList[] = {
72 "AR PL UMing CN Light", 102 "AR PL UMing CN Light",
73 "WenQuanYi Micro Hei", 103 "WenQuanYi Micro Hei",
74 "AR PL UKai CN", 104 "AR PL UKai CN",
75 }; 105 };
76 static const FX_LPCSTR g_LinuxB5FontList[] = { 106 static const FX_LPCSTR g_LinuxB5FontList[] = {
77 "AR PL UMing TW Light", 107 "AR PL UMing TW Light",
78 "WenQuanYi Micro Hei", 108 "WenQuanYi Micro Hei",
79 "AR PL UKai TW", 109 "AR PL UKai TW",
80 }; 110 };
81 static const FX_LPCSTR g_LinuxHGFontList[] = { 111 static const FX_LPCSTR g_LinuxHGFontList[] = {
82 "UnDotum", 112 "UnDotum",
83 }; 113 };
84 static FX_INT32 GetJapanesePreference(FX_LPCSTR facearr, int weight, int picth_f amily) 114 static FX_INT32 GetJapanesePreference(FX_LPCSTR facearr,
85 { 115 int weight,
86 CFX_ByteString face = facearr; 116 int picth_family) {
87 if (face.Find("Gothic") >= 0 || face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e" ) >= 0) { 117 CFX_ByteString face = facearr;
88 if (face.Find("PGothic") >= 0 || face.Find("\x82\x6f\x83\x53\x83\x56\x83 \x62\x83\x4e") >= 0) { 118 if (face.Find("Gothic") >= 0 ||
89 return 0; 119 face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) {
90 } else { 120 if (face.Find("PGothic") >= 0 ||
91 return 1; 121 face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) {
92 } 122 return 0;
93 } else if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) { 123 } else {
94 if (face.Find("PMincho") >= 0 || face.Find("\x82\x6f\x96\xbe\x92\xa9") > = 0) { 124 return 1;
95 return 2; 125 }
96 } else { 126 } else if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) {
97 return 3; 127 if (face.Find("PMincho") >= 0 ||
98 } 128 face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) {
99 } 129 return 2;
100 if (!(picth_family & FXFONT_FF_ROMAN) && weight > 400) { 130 } else {
101 return 0; 131 return 3;
102 } 132 }
103 return 2; 133 }
104 } 134 if (!(picth_family & FXFONT_FF_ROMAN) && weight > 400) {
105 void* CFX_LinuxFontInfo::MapFont(int weight, FX_BOOL bItalic, int charset, int p itch_family, FX_LPCSTR cstr_face, FX_BOOL& bExact)
106 {
107 CFX_ByteString face = cstr_face;
108 int iBaseFont;
109 for (iBaseFont = 0; iBaseFont < 12; iBaseFont ++)
110 if (face == CFX_ByteStringC(Base14Substs[iBaseFont].m_pName)) {
111 face = Base14Substs[iBaseFont].m_pSubstName;
112 bExact = TRUE;
113 break;
114 }
115 if (iBaseFont < 12) {
116 return GetFont(face);
117 }
118 FX_LPVOID p = NULL;
119 FX_BOOL bCJK = TRUE;
120 switch (charset) {
121 case FXFONT_SHIFTJIS_CHARSET: {
122 FX_INT32 index = GetJapanesePreference(cstr_face, weight, pitch_ family);
123 if (index < 0) {
124 break;
125 }
126 for (FX_INT32 i = 0; i < LINUX_GPNAMESIZE; i++)
127 if (m_FontList.Lookup(LinuxGpFontList[index].NameArr[i], p)) {
128 return p;
129 }
130 }
131 break;
132 case FXFONT_GB2312_CHARSET: {
133 static FX_INT32 s_gbCount = sizeof(g_LinuxGbFontList) / sizeof(F X_LPCSTR);
134 for (FX_INT32 i = 0; i < s_gbCount; i++)
135 if (m_FontList.Lookup(g_LinuxGbFontList[i], p)) {
136 return p;
137 }
138 }
139 break;
140 case FXFONT_CHINESEBIG5_CHARSET: {
141 static FX_INT32 s_b5Count = sizeof(g_LinuxB5FontList) / sizeof(F X_LPCSTR);
142 for (FX_INT32 i = 0; i < s_b5Count; i++)
143 if (m_FontList.Lookup(g_LinuxB5FontList[i], p)) {
144 return p;
145 }
146 }
147 break;
148 case FXFONT_HANGEUL_CHARSET: {
149 static FX_INT32 s_hgCount = sizeof(g_LinuxHGFontList) / sizeof(F X_LPCSTR);
150 for (FX_INT32 i = 0; i < s_hgCount; i++)
151 if (m_FontList.Lookup(g_LinuxHGFontList[i], p)) {
152 return p;
153 }
154 }
155 break;
156 default:
157 bCJK = FALSE;
158 break;
159 }
160 if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) {
161 return GetFont("Courier New");
162 }
163 return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK);
164 }
165 static FX_DWORD _LinuxGetCharset(int charset)
166 {
167 switch(charset) {
168 case FXFONT_SHIFTJIS_CHARSET:
169 return CHARSET_FLAG_SHIFTJIS;
170 case FXFONT_GB2312_CHARSET:
171 return CHARSET_FLAG_GB;
172 case FXFONT_CHINESEBIG5_CHARSET:
173 return CHARSET_FLAG_BIG5;
174 case FXFONT_HANGEUL_CHARSET:
175 return CHARSET_FLAG_KOREAN;
176 case FXFONT_SYMBOL_CHARSET:
177 return CHARSET_FLAG_SYMBOL;
178 case FXFONT_ANSI_CHARSET:
179 return CHARSET_FLAG_ANSI;
180 default:
181 break;
182 }
183 return 0; 135 return 0;
184 } 136 }
185 static FX_INT32 _LinuxGetSimilarValue(int weight, FX_BOOL bItalic, int pitch_fam ily, FX_DWORD style) 137 return 2;
186 { 138 }
139 void* CFX_LinuxFontInfo::MapFont(int weight,
140 FX_BOOL bItalic,
141 int charset,
142 int pitch_family,
143 FX_LPCSTR cstr_face,
144 FX_BOOL& bExact) {
145 CFX_ByteString face = cstr_face;
146 int iBaseFont;
147 for (iBaseFont = 0; iBaseFont < 12; iBaseFont++)
148 if (face == CFX_ByteStringC(Base14Substs[iBaseFont].m_pName)) {
149 face = Base14Substs[iBaseFont].m_pSubstName;
150 bExact = TRUE;
151 break;
152 }
153 if (iBaseFont < 12) {
154 return GetFont(face);
155 }
156 FX_LPVOID p = NULL;
157 FX_BOOL bCJK = TRUE;
158 switch (charset) {
159 case FXFONT_SHIFTJIS_CHARSET: {
160 FX_INT32 index = GetJapanesePreference(cstr_face, weight, pitch_family);
161 if (index < 0) {
162 break;
163 }
164 for (FX_INT32 i = 0; i < LINUX_GPNAMESIZE; i++)
165 if (m_FontList.Lookup(LinuxGpFontList[index].NameArr[i], p)) {
166 return p;
167 }
168 } break;
169 case FXFONT_GB2312_CHARSET: {
170 static FX_INT32 s_gbCount = sizeof(g_LinuxGbFontList) / sizeof(FX_LPCSTR);
171 for (FX_INT32 i = 0; i < s_gbCount; i++)
172 if (m_FontList.Lookup(g_LinuxGbFontList[i], p)) {
173 return p;
174 }
175 } break;
176 case FXFONT_CHINESEBIG5_CHARSET: {
177 static FX_INT32 s_b5Count = sizeof(g_LinuxB5FontList) / sizeof(FX_LPCSTR);
178 for (FX_INT32 i = 0; i < s_b5Count; i++)
179 if (m_FontList.Lookup(g_LinuxB5FontList[i], p)) {
180 return p;
181 }
182 } break;
183 case FXFONT_HANGEUL_CHARSET: {
184 static FX_INT32 s_hgCount = sizeof(g_LinuxHGFontList) / sizeof(FX_LPCSTR);
185 for (FX_INT32 i = 0; i < s_hgCount; i++)
186 if (m_FontList.Lookup(g_LinuxHGFontList[i], p)) {
187 return p;
188 }
189 } break;
190 default:
191 bCJK = FALSE;
192 break;
193 }
194 if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) {
195 return GetFont("Courier New");
196 }
197 return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK);
198 }
199 static FX_DWORD _LinuxGetCharset(int charset) {
200 switch (charset) {
201 case FXFONT_SHIFTJIS_CHARSET:
202 return CHARSET_FLAG_SHIFTJIS;
203 case FXFONT_GB2312_CHARSET:
204 return CHARSET_FLAG_GB;
205 case FXFONT_CHINESEBIG5_CHARSET:
206 return CHARSET_FLAG_BIG5;
207 case FXFONT_HANGEUL_CHARSET:
208 return CHARSET_FLAG_KOREAN;
209 case FXFONT_SYMBOL_CHARSET:
210 return CHARSET_FLAG_SYMBOL;
211 case FXFONT_ANSI_CHARSET:
212 return CHARSET_FLAG_ANSI;
213 default:
214 break;
215 }
216 return 0;
217 }
218 static FX_INT32 _LinuxGetSimilarValue(int weight,
219 FX_BOOL bItalic,
220 int pitch_family,
221 FX_DWORD style) {
222 FX_INT32 iSimilarValue = 0;
223 if ((style & FXFONT_BOLD) == (weight > 400)) {
224 iSimilarValue += 16;
225 }
226 if ((style & FXFONT_ITALIC) == bItalic) {
227 iSimilarValue += 16;
228 }
229 if ((style & FXFONT_SERIF) == (pitch_family & FXFONT_FF_ROMAN)) {
230 iSimilarValue += 16;
231 }
232 if ((style & FXFONT_SCRIPT) == (pitch_family & FXFONT_FF_SCRIPT)) {
233 iSimilarValue += 8;
234 }
235 if ((style & FXFONT_FIXED_PITCH) == (pitch_family & FXFONT_FF_FIXEDPITCH)) {
236 iSimilarValue += 8;
237 }
238 return iSimilarValue;
239 }
240 void* CFX_LinuxFontInfo::FindFont(int weight,
241 FX_BOOL bItalic,
242 int charset,
243 int pitch_family,
244 FX_LPCSTR family,
245 FX_BOOL bMatchName) {
246 CFontFaceInfo* pFind = NULL;
247 FX_DWORD charset_flag = _LinuxGetCharset(charset);
248 FX_INT32 iBestSimilar = 0;
249 FX_POSITION pos = m_FontList.GetStartPosition();
250 while (pos) {
251 CFX_ByteString bsName;
252 CFontFaceInfo* pFont = NULL;
253 m_FontList.GetNextAssoc(pos, bsName, (FX_LPVOID&)pFont);
254 if (!(pFont->m_Charsets & charset_flag) &&
255 charset != FXFONT_DEFAULT_CHARSET) {
256 continue;
257 }
187 FX_INT32 iSimilarValue = 0; 258 FX_INT32 iSimilarValue = 0;
188 if ((style & FXFONT_BOLD) == (weight > 400)) { 259 FX_INT32 index = bsName.Find(family);
189 iSimilarValue += 16; 260 if (bMatchName && index < 0) {
190 } 261 continue;
191 if ((style & FXFONT_ITALIC) == bItalic) { 262 }
192 iSimilarValue += 16; 263 if (!bMatchName && index > 0) {
193 } 264 iSimilarValue += 64;
194 if ((style & FXFONT_SERIF) == (pitch_family & FXFONT_FF_ROMAN)) { 265 }
195 iSimilarValue += 16; 266 iSimilarValue =
196 } 267 _LinuxGetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles);
197 if ((style & FXFONT_SCRIPT) == (pitch_family & FXFONT_FF_SCRIPT)) { 268 if (iSimilarValue > iBestSimilar) {
198 iSimilarValue += 8; 269 iBestSimilar = iSimilarValue;
199 } 270 pFind = pFont;
200 if ((style & FXFONT_FIXED_PITCH) == (pitch_family & FXFONT_FF_FIXEDPITCH)) { 271 }
201 iSimilarValue += 8; 272 }
202 } 273 return pFind;
203 return iSimilarValue; 274 }
204 } 275 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() {
205 void* CFX_LinuxFontInfo::FindFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, FX_LPCSTR family, FX_BOOL bMatchName) 276 CFX_LinuxFontInfo* pInfo = FX_NEW CFX_LinuxFontInfo;
206 { 277 if (!pInfo) {
207 CFontFaceInfo* pFind = NULL; 278 return NULL;
208 FX_DWORD charset_flag = _LinuxGetCharset(charset); 279 }
209 FX_INT32 iBestSimilar = 0; 280 if (!pInfo->ParseFontCfg()) {
210 FX_POSITION pos = m_FontList.GetStartPosition(); 281 pInfo->AddPath("/usr/share/fonts");
211 while (pos) { 282 pInfo->AddPath("/usr/share/X11/fonts/Type1");
212 CFX_ByteString bsName; 283 pInfo->AddPath("/usr/share/X11/fonts/TTF");
213 CFontFaceInfo* pFont = NULL; 284 pInfo->AddPath("/usr/local/share/fonts");
214 m_FontList.GetNextAssoc(pos, bsName, (FX_LPVOID&)pFont); 285 }
215 if (!(pFont->m_Charsets & charset_flag) && charset != FXFONT_DEFAULT_CHA RSET) { 286 return pInfo;
216 continue; 287 }
217 } 288 FX_BOOL CFX_LinuxFontInfo::ParseFontCfg() {
218 FX_INT32 iSimilarValue = 0; 289 return FALSE;
219 FX_INT32 index = bsName.Find(family); 290 }
220 if (bMatchName && index < 0) { 291 void CFX_GEModule::InitPlatform() {
221 continue; 292 m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault());
222 } 293 }
223 if (!bMatchName && index > 0) { 294 void CFX_GEModule::DestroyPlatform() {
224 iSimilarValue += 64;
225 }
226 iSimilarValue = _LinuxGetSimilarValue(weight, bItalic, pitch_family, pFo nt->m_Styles);
227 if (iSimilarValue > iBestSimilar) {
228 iBestSimilar = iSimilarValue;
229 pFind = pFont;
230 }
231 }
232 return pFind;
233 }
234 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault()
235 {
236 CFX_LinuxFontInfo* pInfo = FX_NEW CFX_LinuxFontInfo;
237 if (!pInfo) {
238 return NULL;
239 }
240 if (!pInfo->ParseFontCfg()) {
241 pInfo->AddPath("/usr/share/fonts");
242 pInfo->AddPath("/usr/share/X11/fonts/Type1");
243 pInfo->AddPath("/usr/share/X11/fonts/TTF");
244 pInfo->AddPath("/usr/local/share/fonts");
245 }
246 return pInfo;
247 }
248 FX_BOOL CFX_LinuxFontInfo::ParseFontCfg()
249 {
250 return FALSE;
251 }
252 void CFX_GEModule::InitPlatform()
253 {
254 m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault());
255 }
256 void CFX_GEModule::DestroyPlatform()
257 {
258 } 295 }
259 #endif 296 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698