├── Apps
├── StyleChecker
│ ├── background.png
│ ├── StyleCheckerAppDelegate.h
│ ├── StyleCheckerViewController.h
│ ├── main.m
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── StyleCheckerAppDelegate.m
├── Common
│ ├── SVGUtil.h
│ ├── SVGUtil.m
│ ├── DirectoryContentsViewController.h
│ └── DirectoryContentsViewController.m
├── DtdVerifier
│ └── main.c
├── BatchRenderer
│ └── main.m
└── CommandLineRenderer
│ └── main.m
├── AcceptanceTest
├── Golden
│ └── Example
│ │ └── circle.png
├── Info.plist
└── AcceptanceTest.m
├── .gitignore
├── MetroSVG.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ ├── AcceptanceTest.xcscheme
│ ├── DTDVerifier.xcscheme
│ ├── BatchRenderer.xcscheme
│ ├── StyleChecker.xcscheme
│ ├── CommandLineRenderer.xcscheme
│ ├── MetroSVG-iOS.xcscheme
│ └── MetroSVG-OS-X.xcscheme
├── TestData
└── Example
│ └── circle.svg
├── UnitTest-OS-X
└── Info.plist
├── UnitTest-iOS
└── Info.plist
├── MetroSVG
├── Public
│ ├── MSCDebug.h
│ ├── MSCStyleSheet.h
│ └── MSCDocument.h
├── Internal
│ ├── Constants.h
│ ├── Macros.h
│ ├── Debug.h
│ ├── Constants.cc
│ ├── BasicTypes.cc
│ ├── Document.h
│ ├── Debug.cc
│ ├── TransformIterator.h
│ ├── StyleSheet.h
│ ├── StyleIterator.h
│ ├── DocumentTest.mm
│ ├── StringPiece.cc
│ ├── SVGStandardColor.h
│ ├── StyleIterator.cc
│ ├── Gradient.h
│ ├── StringPieceTest.mm
│ ├── StringPiece.h
│ ├── LoggingUtils.h
│ ├── Gradient.cc
│ ├── StyleIteratorTest.mm
│ ├── BasicTypes.h
│ ├── PathDataIterator.h
│ ├── Utils.h
│ ├── TransformIterator.cc
│ ├── Document.cc
│ ├── LoggingUtils.cc
│ ├── StyleSheet.cc
│ ├── BasicValueParsers.h
│ ├── Utils.cc
│ ├── StyleSheetTest.mm
│ ├── SVGStandardColor.cc
│ ├── Renderer.h
│ └── PathDataIterator.cc
├── iOS
│ ├── MSVGStyleSheet+Internal.h
│ ├── MSVGStyleSheet.h
│ ├── MSVGStyleSheet.mm
│ ├── MSVGDocument.h
│ └── MSVGDocument.mm
├── MetroSVG_Sources.mm
├── MetroSVG.h
└── MetroSVG_Sources.cc
├── CONTRIBUTING
├── README.md
├── ProjectScripts
└── copy_files.sh
└── LICENSE
/Apps/StyleChecker/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google/metrosvg/HEAD/Apps/StyleChecker/background.png
--------------------------------------------------------------------------------
/AcceptanceTest/Golden/Example/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google/metrosvg/HEAD/AcceptanceTest/Golden/Example/circle.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | .DS_Store
3 | *.xcodeproj/project.xcworkspace/xcuserdata
4 | *.xcodeproj/xcuserdata
5 | TestData/UserData
6 | AcceptanceTest/Golden/UserData
7 |
--------------------------------------------------------------------------------
/MetroSVG.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TestData/Example/circle.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/UnitTest-OS-X/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/UnitTest-iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/AcceptanceTest/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Apps/StyleChecker/StyleCheckerAppDelegate.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | @interface StyleCheckerAppDelegate : UIResponder
20 |
21 | @property (strong, nonatomic) UIWindow *window;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/MetroSVG/Public/MSCDebug.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #if defined __cplusplus
20 | extern "C" {
21 | #endif
22 |
23 | void MSCSetCoreGraphicsCallLoggingEnabled(int enabled);
24 |
25 | #if defined __cplusplus
26 | } // extern "C"
27 | #endif
28 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Constants.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 |
21 | namespace metrosvg {
22 | namespace internal {
23 |
24 | extern const CGFloat kPi;
25 |
26 | } // namespace internal
27 | } // namespace metrosvg
28 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Macros.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
20 |
21 | #define DISALLOW_COPY_AND_ASSIGN(class_name) \
22 | class_name(const class_name &rhs); \
23 | const class_name &operator=(const class_name &rhs);
24 |
--------------------------------------------------------------------------------
/MetroSVG/iOS/MSVGStyleSheet+Internal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import "MetroSVG/iOS/MSVGStyleSheet.h"
18 |
19 | #include "MetroSVG/Public/MSCStyleSheet.h"
20 |
21 | @interface MSVGStyleSheet ()
22 |
23 | @property(nonatomic, readonly) MSCStyleSheet *styleSheet;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Debug.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include "MetroSVG/Public/MSCDebug.h"
20 |
21 | namespace metrosvg {
22 | namespace internal {
23 |
24 | bool GetCoreGraphicsCallLoggingEnabled();
25 |
26 | } // namespace internal
27 | } // namespace metrosvg
28 |
--------------------------------------------------------------------------------
/Apps/StyleChecker/StyleCheckerViewController.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | @interface StyleCheckerViewController : UIViewController
20 |
21 | - (instancetype)initWithPath:(NSString *)path
22 | cssFiles:(NSArray *)cssFiles;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Constants.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/Constants.h"
18 |
19 | #include
20 |
21 | namespace metrosvg {
22 | namespace internal {
23 |
24 | const CGFloat kPi = static_cast(M_PI);
25 |
26 | } // namespace internal
27 | } // namespace metrosvg
28 |
--------------------------------------------------------------------------------
/Apps/StyleChecker/main.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #import "StyleCheckerAppDelegate.h"
20 |
21 | int main(int argc, char *argv[]) {
22 | @autoreleasepool {
23 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([StyleCheckerAppDelegate class]));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/MetroSVG/iOS/MSVGStyleSheet.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | // MSVGStyleSheet represents a set of CSS rules.
20 | @interface MSVGStyleSheet : NSObject
21 |
22 | // Initializes the receiver with UTF-8-encoded CSS data.
23 | - (instancetype)initWithData:(NSData *)data;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Apps/Common/SVGUtil.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | @interface SVGUtil : NSObject
21 |
22 | + (CGImageRef)imageWithSVGFile:(NSString *)file size:(CGSize)size;
23 |
24 | + (void)writeImage:(CGImageRef)image toPNGFile:(NSString *)file;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/MetroSVG/MetroSVG_Sources.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include
18 |
19 | _Static_assert(TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR,
20 | "This file is for iOS.");
21 |
22 | #include "MetroSVG/MetroSVG_Sources.cc"
23 | #import "MetroSVG/iOS/MSVGDocument.mm"
24 | #import "MetroSVG/iOS/MSVGStyleSheet.mm"
25 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/BasicTypes.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/BasicTypes.h"
18 |
19 | #include "MetroSVG/Internal/Utils.h"
20 |
21 | namespace metrosvg {
22 | namespace internal {
23 |
24 | RgbColor::RgbColor(CGFloat red, CGFloat green, CGFloat blue)
25 | : red_(ClampToUnitRange(red)),
26 | green_(ClampToUnitRange(green)),
27 | blue_(ClampToUnitRange(blue)) {}
28 |
29 | } // namespace internal
30 | } // namespace metrosvg
31 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Document.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include "MetroSVG/Public/MSCDocument.h"
20 |
21 | // Represents a partially parsed SVG document.
22 | struct MSCDocument {
23 | const char *data;
24 | size_t data_length;
25 | const char *url;
26 |
27 | // Value of the width and height attributes of the outmost svg element.
28 | CGSize size;
29 | // Value of the viewBox attribute of the outmost svg element.
30 | CGRect view_box;
31 | };
32 |
--------------------------------------------------------------------------------
/MetroSVG/iOS/MSVGStyleSheet.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import "MetroSVG/iOS/MSVGStyleSheet+Internal.h"
18 |
19 | @implementation MSVGStyleSheet
20 |
21 | - (instancetype)initWithData:(NSData *)data {
22 | self = [super init];
23 | if (self) {
24 | _styleSheet =
25 | MSCStyleSheetCreateWithData(
26 | reinterpret_cast(data.bytes), data.length);
27 | }
28 | return self;
29 | }
30 |
31 | - (void)dealloc {
32 | MSCStyleSheetDelete(_styleSheet);
33 | _styleSheet = NULL;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Debug.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/Debug.h"
18 |
19 | namespace metrosvg {
20 | namespace internal {
21 |
22 | namespace {
23 | bool g_coreGraphicsCallLoggingEnabled = false;
24 | } // namespace
25 |
26 | bool GetCoreGraphicsCallLoggingEnabled() {
27 | return g_coreGraphicsCallLoggingEnabled;
28 | }
29 |
30 | } // namespace internal
31 | } // namespace metrosvg
32 |
33 | void MSCSetCoreGraphicsCallLoggingEnabled(int enabled) {
34 | metrosvg::internal::g_coreGraphicsCallLoggingEnabled = (enabled != 0);
35 | }
36 |
--------------------------------------------------------------------------------
/MetroSVG/MetroSVG.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // The umbrella header of MetroSVG. This file can be included by both C and
18 | // Objective-C code.
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | #include "MetroSVG/Public/MSCDebug.h"
25 | #include "MetroSVG/Public/MSCDocument.h"
26 | #include "MetroSVG/Public/MSCStyleSheet.h"
27 |
28 | #ifdef __OBJC__
29 | #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
30 |
31 | #import "MetroSVG/iOS/MSVGDocument.h"
32 | #import "MetroSVG/iOS/MSVGStyleSheet.h"
33 |
34 | #endif // TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
35 | #endif // __OBJC__
36 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/TransformIterator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 |
21 | namespace metrosvg {
22 | namespace internal {
23 |
24 | class StringPiece;
25 |
26 | class TransformIterator {
27 | public:
28 | explicit TransformIterator(StringPiece *s);
29 |
30 | bool Next();
31 | const CGAffineTransform &transform() const { return transform_; }
32 |
33 | private:
34 | void ConsumeTransformDelimeters(StringPiece *s) const;
35 |
36 | StringPiece *s_;
37 | CGAffineTransform transform_;
38 | bool is_first;
39 | };
40 |
41 | } // namespace internal
42 | } // namespace metrosvg
43 |
--------------------------------------------------------------------------------
/MetroSVG/Public/MSCStyleSheet.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #if defined __cplusplus
20 | extern "C" {
21 | #endif
22 |
23 | // MSCStyleSheet is an opaque type that represents a set of CSS rules.
24 | typedef struct MSCStyleSheet MSCStyleSheet;
25 |
26 | // Creates an MSCStyleSheet instance with UTF-8-encoded CSS data. The instance
27 | // must be deleted with MSCStyleSheetDelete when it is done.
28 | MSCStyleSheet *MSCStyleSheetCreateWithData(const char *data, size_t length);
29 |
30 | // Delets an MSCStyleSheet instance.
31 | void MSCStyleSheetDelete(MSCStyleSheet *style_sheet);
32 |
33 | #if defined __cplusplus
34 | } // extern "C"
35 | #endif
36 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/StyleSheet.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 | #include
21 |
22 | #include "MetroSVG/Public/MSCStylesheet.h"
23 |
24 | struct MSCStyleSheet {
25 | std::map>> entry;
26 | };
27 |
28 | namespace metrosvg {
29 | namespace internal {
30 |
31 | // Caller should release the returned instance.
32 | MSCStyleSheet *ParseStyleSheetData(const char *data,
33 | size_t data_length);
34 |
35 | // Merge css content in source into dest.
36 | void MSCStyleSheetMerge(const MSCStyleSheet &source,
37 | MSCStyleSheet *dest);
38 |
39 | } // namespace internal
40 | } // namespace metrosvg
41 |
--------------------------------------------------------------------------------
/MetroSVG/MetroSVG_Sources.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/BasicTypes.cc"
18 | #include "MetroSVG/Internal/BasicValueParsers.cc"
19 | #include "MetroSVG/Internal/Constants.cc"
20 | #include "MetroSVG/Internal/Debug.cc"
21 | #include "MetroSVG/Internal/Document.cc"
22 | #include "MetroSVG/Internal/Gradient.cc"
23 | #include "MetroSVG/Internal/LoggingUtils.cc"
24 | #include "MetroSVG/Internal/PathDataIterator.cc"
25 | #include "MetroSVG/Internal/Renderer.cc"
26 | #include "MetroSVG/Internal/StringPiece.cc"
27 | #include "MetroSVG/Internal/StyleIterator.cc"
28 | #include "MetroSVG/Internal/StyleSheet.cc"
29 | #include "MetroSVG/Internal/SVGStandardColor.cc"
30 | #include "MetroSVG/Internal/TransformIterator.cc"
31 | #include "MetroSVG/Internal/Utils.cc"
32 |
--------------------------------------------------------------------------------
/Apps/StyleChecker/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/MetroSVG/Internal/StyleIterator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 |
21 | #include "MetroSVG/Internal/StringPiece.h"
22 |
23 | namespace metrosvg {
24 | namespace internal {
25 |
26 | class StyleIterator {
27 | public:
28 | StyleIterator(StringPiece *s,
29 | const std::unordered_set &supported_properties);
30 |
31 | // Sets property and value to the next style in supported_properties.
32 | bool Next();
33 | const StringPiece &property() const { return property_; }
34 | const StringPiece &value() const { return value_; }
35 |
36 | private:
37 | StringPiece *s_;
38 | StringPiece property_;
39 | StringPiece value_;
40 | const std::unordered_set supported_properties_;
41 | };
42 |
43 | } // namespace internal
44 | } // namespace metrosvg
45 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/DocumentTest.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include
18 |
19 | #import
20 |
21 | #include "MetroSVG/Internal/Document.h"
22 |
23 | @interface DocumentTest : XCTestCase
24 | @end
25 |
26 | @implementation DocumentTest
27 |
28 | - (void)testGetImageAspectRatio {
29 | std::string data = " ";
30 | MSCDocument *document =
31 | MSCDocumentCreateFromData(data.c_str(), data.size(), "");
32 | XCTAssert(CGRectEqualToRect(MSCDocumentGetImageViewBox(document),
33 | CGRectMake(0, 0, 640, 480)));
34 | MSCDocumentDelete(document);
35 | }
36 |
37 | - (void)testGetImageAspectRatio_ImplicitDefault {
38 | // TODO: What to do when viewBox is not specified?
39 | }
40 |
41 |
42 | // TODO: Write more tests of SVGDocument* public functions.
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/CONTRIBUTING:
--------------------------------------------------------------------------------
1 | Want to contribute? Great! First, read this page (including the small print at the end).
2 |
3 | ### Before you contribute
4 | Before we can use your code, you must sign the
5 | [Google Individual Contributor License Agreement]
6 | (https://cla.developers.google.com/about/google-individual)
7 | (CLA), which you can do online. The CLA is necessary mainly because you own the
8 | copyright to your changes, even after your contribution becomes part of our
9 | codebase, so we need your permission to use and distribute your code. We also
10 | need to be sure of various other things—for instance that you'll tell us if you
11 | know that your code infringes on other people's patents. You don't have to sign
12 | the CLA until after you've submitted your code for review and a member has
13 | approved it, but you must do it before we can put your code into our codebase.
14 | Before you start working on a larger contribution, you should get in touch with
15 | us first through the issue tracker with your idea so that we can help out and
16 | possibly guide you. Coordinating up front makes it much easier to avoid
17 | frustration later on.
18 |
19 | ### Code reviews
20 | All submissions, including submissions by project members, require review. We
21 | use Github pull requests for this purpose.
22 |
23 | ### The small print
24 | Contributions made by corporations are covered by a different agreement than
25 | the one above, the
26 | [Software Grant and Corporate Contributor License Agreement]
27 | (https://cla.developers.google.com/about/google-corporate).
28 |
--------------------------------------------------------------------------------
/Apps/Common/SVGUtil.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import "Apps/Common/SVGUtil.h"
18 |
19 | #import "MetroSVG/MetroSVG.h"
20 |
21 | @implementation SVGUtil
22 |
23 | + (CGImageRef)imageWithSVGFile:(NSString *)file size:(CGSize)size {
24 | NSData *svgData = [NSData dataWithContentsOfFile:file];
25 | MSCDocument *document = MSCDocumentCreateFromData([svgData bytes], [svgData length], "");
26 | CGImageRef image = MSCDocumentCreateCGImage(document, size, NULL);
27 | MSCDocumentDelete(document);
28 | return image;
29 | }
30 |
31 | + (void)writeImage:(CGImageRef)image toPNGFile:(NSString *)file {
32 | NSURL *url = [NSURL fileURLWithPath:file];
33 | CGImageDestinationRef destination =
34 | CGImageDestinationCreateWithURL((__bridge CFURLRef)url, kUTTypePNG, 1, NULL);
35 | CGImageDestinationAddImage(destination, image, NULL);
36 | CGImageDestinationFinalize(destination);
37 | CFRelease(destination);
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/StringPiece.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/StringPiece.h"
18 |
19 | #include
20 |
21 | namespace metrosvg {
22 | namespace internal {
23 |
24 | const std::string StringPiece::as_std_string() const {
25 | return std::string(begin_, length_);
26 | }
27 |
28 | void StringPiece::Advance(size_t n) {
29 | begin_ = begin_ + std::min(n, length_);
30 | length_ = length_ - std::min(n, length_);
31 | }
32 |
33 | size_t StringPiece::find(char c) const {
34 | const char *iter = std::find(begin_, end(), c);
35 | if (iter == end()) {
36 | return std::string::npos;
37 | } else {
38 | return iter - begin_;
39 | }
40 | }
41 |
42 | size_t StringPiece::find(const StringPiece &s) const {
43 | const char * pos = std::search(begin_, end(), s.begin_, s.end());
44 | if (pos == end()) {
45 | return std::string::npos;
46 | } else {
47 | return pos - begin_;
48 | }
49 | }
50 |
51 | } // namespace internal
52 | } // namespace metrosvg
53 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #MetroSVG
2 |
3 | MetroSVG is a production-quality SVG renderer implementation for iOS
4 | and OS X. It is used in Google Maps for iOS.
5 |
6 | The library provides an Objective-C interface for iOS and a C
7 | interface for iOS and OS X.
8 |
9 | ##Usage
10 | #import "MetroSVG/MetroSVG.h"
11 |
12 | NSData *svgData = ...;
13 | MSVGDocument *svgDocument = [[MSVGDocument alloc] initWithData:svgData];
14 | UIImage *svgImage = [svgDocument imageWithSize:svgDocument.size];
15 |
16 | ##Supported Features
17 | MetroSVG is intended to cover the most common use cases of SVG in native iOS app development where designers create and export image assets using graphics tools such as Illustrator and Inkscape. Therefore, it is specialized for rendering of static images by design. Below is a list of SVG 1.1 features and their implementation status.
18 |
19 |
20 | Feature | Status
21 | --- | ---
22 | Paths and Basic Shapes | Feature complete.
23 | Coordinate Systems and Transformations | Feature complete.
24 | Gradients | Near feature complete.
25 | Fill and Stroke Properties | Near feature complete.
26 | Document Structure | Only <svg> and <g> are implemented.
27 | Styling (CSS) | An experimental implementation of class selector is available.
28 | Clipping, Masking, Patterns, Markers, Length Units | Not implemented.
29 | Text, Fonts, Filter Effects | Not implemented. Recommended to use other options.
30 | Color Profile, Linking, Interactivity, Scripting, Animation | Out of scope.
31 |
32 | ##Discussion Forum
33 | https://groups.google.com/forum/#!forum/metrosvg
34 |
35 | ##Disclaimer
36 | MetroSVG is not an official Google product.
37 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/SVGStandardColor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include "MetroSVG/Internal/StringPiece.h"
20 |
21 | // If this symbol is externally set to 0, SVG color keyword support
22 | // will be omitted. Color keyword support causes the object code
23 | // size to increase by about 1100 bytes.
24 | #if !defined(SVG_COLOR_KEYWORD_SUPPORT)
25 | #define SVG_COLOR_KEYWORD_SUPPORT 1
26 | #endif // !defined(SVG_COLOR_KEYWORD_SUPPORT)
27 |
28 | #if SVG_COLOR_KEYWORD_SUPPORT
29 |
30 | namespace metrosvg {
31 | namespace internal {
32 |
33 | // This is a struct that can be statically initialized with the
34 | // definitions of the standard SVG colors.
35 | struct SvgStandardColorDefinition {
36 | const char *name;
37 | uint8_t red;
38 | uint8_t green;
39 | uint8_t blue;
40 | uint8_t alpha;
41 | };
42 | const SvgStandardColorDefinition *FindSVGStandardColorOrNull(
43 | const StringPiece &token);
44 |
45 | } // namespace internal
46 | } // namespace metrosvg
47 |
48 | #endif // SVG_COLOR_KEYWORD_SUPPORT
49 |
--------------------------------------------------------------------------------
/Apps/Common/DirectoryContentsViewController.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | @protocol DirectoryContentsViewControllerDataSource;
20 |
21 | /**
22 | * DirectoryContentsViewController implements traversal of directory trees using
23 | * usual combination of table views and the navigation stack. When traversal
24 | * reaches a tree leave (non-directory files), it creates a view controller from
25 | * its data source that presents files in a way specific to the application.
26 | *
27 | * It can handle multiple parallel directory trees.
28 | */
29 | @interface DirectoryContentsViewController : UITableViewController
30 |
31 | @property(nonatomic, weak) id dataSource;
32 |
33 | - (instancetype)initWithPaths:(NSArray *)paths title:(NSString *)title;
34 |
35 | @end
36 |
37 | @protocol DirectoryContentsViewControllerDataSource
38 |
39 | - (UIViewController *)
40 | directoryContentsController:(DirectoryContentsViewController *)directoryContentsController
41 | viewControllerWithFilePaths:(NSArray *)filePaths;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Apps/StyleChecker/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/MetroSVG/iOS/MSVGDocument.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | @class MSVGStyleSheet;
21 |
22 | // MSVGDocument represents an SVG document.
23 | @interface MSVGDocument : NSObject
24 |
25 | // The image's intrinsic size as defined by "width" and "height" attributes of
26 | // the outermost svg element. If these attributes are not specified, zero is
27 | // assumed.
28 | @property(nonatomic, readonly) CGSize size;
29 |
30 | // Value of "viewBox" attribute of the outermost svg element. Returns CGRectNull
31 | // if the attribute is not specified.
32 | @property(nonatomic, readonly) CGRect viewBox;
33 |
34 | // Initializes the receiver with UTF-8-encoded SVG data. The data will be
35 | // partially parsed to populate the receiver's properties.
36 | - (instancetype)initWithData:(NSData *)data;
37 |
38 | // Fully parses the data and renders it into a UIImage. The returned image
39 | // has the appropriate density for the screen scale.
40 | - (UIImage *)imageWithSize:(CGSize)size;
41 |
42 | // Same as -imageWithSize: but takes an optional style sheet argument.
43 | - (UIImage *)imageWithSize:(CGSize)size styleSheet:(MSVGStyleSheet *)styleSheet;
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/Apps/StyleChecker/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UIStatusBarTintParameters
32 |
33 | UINavigationBar
34 |
35 | Style
36 | UIBarStyleDefault
37 | Translucent
38 |
39 |
40 |
41 | UISupportedInterfaceOrientations
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationLandscapeLeft
45 | UIInterfaceOrientationLandscapeRight
46 |
47 | UISupportedInterfaceOrientations~ipad
48 |
49 | UIInterfaceOrientationPortrait
50 | UIInterfaceOrientationPortraitUpsideDown
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/ProjectScripts/copy_files.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -eu
2 | #
3 | # Copyright 2015 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | ################################################################################
18 | #
19 |
20 | #!/bin/bash
21 | #
22 | # This script copies the test data suite to an application-specific
23 | # location.
24 | #
25 | # ==== Usage ====
26 | #
27 | # $ ./copy_files.sh [destination]
28 | #
29 | # The optional destinaiton is the directory that files will be copied
30 | # to. When it is not specified, the resource directory of an app's
31 | # main bundle is used, which is always a reasonable default for build
32 | # target types that create a bundle.
33 |
34 | if [[ $# -ge 1 ]]; then
35 | destination="$1"
36 | else
37 | destination="${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
38 | fi
39 |
40 | function install_files() {
41 | local source=$1
42 | local target=$2
43 | mkdir -p "$target"
44 | # Don't drop "/" after $source. rsync changes its behavior based on it.
45 | rsync -a --include="*/" --include="*.svg" --include="*.png" --exclude="*" "${source}/" "$target"
46 | }
47 |
48 | install_files \
49 | "${SRCROOT}/TestData" \
50 | "${destination}/TestData"
51 |
52 | install_files \
53 | "${SRCROOT}/AcceptanceTest/Golden" \
54 | "${destination}/Golden"
55 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/StyleIterator.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/StyleIterator.h"
18 |
19 | #include "MetroSVG/Internal/BasicValueParsers.h"
20 |
21 | namespace metrosvg {
22 | namespace internal {
23 |
24 | StyleIterator::StyleIterator(
25 | StringPiece *s,
26 | const std::unordered_set &supported_properties)
27 | : s_(s),
28 | supported_properties_(supported_properties) {}
29 |
30 | bool StyleIterator::Next() {
31 | ConsumeWhitespace(s_);
32 | if (s_->length() == 0) {
33 | return false;
34 | }
35 | size_t pos = s_->find(':');
36 | if (pos == std::string::npos) {
37 | // TODO: throw exception
38 | return false;
39 | }
40 | property_ = TrimTrailingWhitespace(StringPiece(s_->begin(), pos));
41 | s_->Advance(pos + 1);
42 |
43 | ConsumeWhitespace(s_);
44 | pos = s_->find(';');
45 | if (pos == std::string::npos) {
46 | value_ = TrimTrailingWhitespace(*s_);
47 | s_->Advance(s_->length());
48 | } else {
49 | value_ = TrimTrailingWhitespace(StringPiece(s_->begin(), pos));
50 | s_->Advance(pos + 1);
51 | }
52 |
53 | if (supported_properties_.count(property_.as_std_string())) {
54 | return true;
55 | }
56 | return Next();
57 | }
58 |
59 | } // namespace internal
60 | } // namespace metrosvg
61 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Gradient.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 | #include
21 |
22 | #include
23 |
24 | #include "MetroSVG/Internal/BasicTypes.h"
25 |
26 | namespace metrosvg {
27 | namespace internal {
28 |
29 | struct Gradient;
30 |
31 | CGGradientRef CreateCGGradient(const Gradient &gradient);
32 |
33 | struct GradientStop {
34 | CGFloat offset;
35 | RgbColor color;
36 | CGFloat opacity;
37 |
38 | GradientStop(CGFloat offset_in, RgbColor color_in, CGFloat opacity_in)
39 | : offset(offset_in), color(color_in), opacity(opacity_in) {}
40 | };
41 |
42 | struct Gradient {
43 | enum Type {
44 | kTypeLinear,
45 | kTypeRadial,
46 | };
47 |
48 | enum Units {
49 | kUnitsObjectBoundingBox,
50 | kUnitsUserSpaceOnUse,
51 | };
52 |
53 | struct Linear {
54 | Length x1, y1, x2, y2;
55 | };
56 |
57 | struct Radial {
58 | Length fx, fy, cx, cy, r;
59 | };
60 |
61 | Type type;
62 | std::string id;
63 | std::vector stops;
64 | std::vector transforms;
65 | Units units;
66 |
67 | union {
68 | Linear linear;
69 | Radial radial;
70 | };
71 |
72 | Gradient(Type type_in, const StringMap &attributes);
73 | };
74 |
75 | } // namespace internal
76 | } // namespace metrosvg
77 |
--------------------------------------------------------------------------------
/Apps/DtdVerifier/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | /**
18 | * DTDVerifier verifies an xml file with a given dtd.
19 | *
20 | * Usage:
21 | * $ DTDVerifier xml_file dtd_file
22 | */
23 |
24 | #include
25 |
26 | int main(int argc, const char *argv[]) {
27 | int status = 0;
28 | xmlParserCtxtPtr parser_context = 0;
29 | xmlDocPtr doc = 0;
30 | xmlDtdPtr dtd = 0;
31 | xmlValidCtxtPtr valid_context = 0;
32 |
33 | do {
34 | if (argc < 3) {
35 | status = 2;
36 | fprintf(stderr, "Too few arguments.\n");
37 | break;
38 | }
39 |
40 | parser_context = xmlNewParserCtxt();
41 | doc = xmlCtxtReadFile(parser_context, argv[1], NULL, 0);
42 | if (!doc) {
43 | status = 3;
44 | fprintf(stderr, "Can't read xml.\n");
45 | break;
46 | }
47 |
48 | dtd = xmlParseDTD(NULL, (const xmlChar *)argv[2]);
49 | if (!dtd) {
50 | status = 4;
51 | fprintf(stderr, "Can't read dtd.\n");
52 | break;
53 | }
54 |
55 | valid_context = xmlNewValidCtxt();
56 | status = xmlValidateDtd(valid_context, doc, dtd) ? 0 : 1;
57 | } while (0);
58 |
59 | if (parser_context) xmlFreeParserCtxt(parser_context);
60 | if (doc) xmlFreeDoc(doc);
61 | if (dtd) xmlFreeDtd(dtd);
62 | if (valid_context) xmlFreeValidCtxt(valid_context);
63 |
64 | return status;
65 | }
66 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/StringPieceTest.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #include "MetroSVG/Internal/StringPiece.h"
20 |
21 | using namespace metrosvg::internal;
22 |
23 | @interface StringPieceTest : XCTestCase
24 | @end
25 |
26 | @implementation StringPieceTest
27 |
28 | - (void)testEqualsOperator_Char {
29 | StringPiece lhs("abc");
30 | XCTAssertTrue(lhs == "abc");
31 | XCTAssertFalse(lhs == "ab");
32 | XCTAssertFalse(lhs == "abcd");
33 | XCTAssertFalse(lhs == "abe");
34 | XCTAssertFalse(lhs == "");
35 | XCTAssertFalse(lhs == NULL);
36 | }
37 |
38 | - (void)testFind_Char {
39 | StringPiece s("abcabc");
40 | XCTAssertEqual(s.find('a'), size_t(0));
41 | XCTAssertEqual(s.find('b'), size_t(1));
42 | XCTAssertEqual(s.find('c'), size_t(2));
43 | XCTAssertEqual(s.find('d'), std::string::npos);
44 | }
45 |
46 | - (void)testFind_Char_EmptyTarget {
47 | StringPiece s;
48 | XCTAssertEqual(s.find('a'), std::string::npos);
49 | }
50 |
51 | - (void)testFind_StdString {
52 | StringPiece s("abcdabcd");
53 | XCTAssertEqual(s.find("ab"), size_t(0));
54 | XCTAssertEqual(s.find("bc"), size_t(1));
55 | XCTAssertEqual(s.find("cd"), size_t(2));
56 | XCTAssertEqual(s.find("de"), std::string::npos);
57 | }
58 |
59 | - (void)testFind_StdString_EmptyTarget {
60 | StringPiece s;
61 | XCTAssertEqual(s.find("ab"), std::string::npos);
62 | }
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/MetroSVG.xcodeproj/xcshareddata/xcschemes/AcceptanceTest.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
14 |
15 |
17 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
39 |
40 |
41 |
42 |
48 |
49 |
51 |
52 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/MetroSVG/iOS/MSVGDocument.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import "MetroSVG/iOS/MSVGDocument.h"
18 |
19 | #include "MetroSVG/Public/MSCDocument.h"
20 | #import "MetroSVG/iOS/MSVGStyleSheet+Internal.h"
21 |
22 | @implementation MSVGDocument {
23 | MSCDocument *_document;
24 | }
25 |
26 | - (instancetype)initWithData:(NSData *)data {
27 | self = [super init];
28 | if (self) {
29 | _document =
30 | MSCDocumentCreateFromData(reinterpret_cast(data.bytes),
31 | data.length,
32 | "");
33 | }
34 | return self;
35 | }
36 |
37 | - (void)dealloc {
38 | MSCDocumentDelete(_document);
39 | _document = NULL;
40 | }
41 |
42 | - (CGSize)size {
43 | return MSCDocumentGetImageSize(_document);
44 | }
45 |
46 | - (CGRect)viewBox {
47 | return MSCDocumentGetImageViewBox(_document);
48 | }
49 |
50 | - (UIImage *)imageWithSize:(CGSize)size {
51 | return [self imageWithSize:size styleSheet:NULL];
52 | }
53 |
54 | - (UIImage *)imageWithSize:(CGSize)size
55 | styleSheet:(MSVGStyleSheet *)styleSheet {
56 | CGFloat scale = [UIScreen mainScreen].scale;
57 | CGSize canvasSize = CGSizeMake(size.width * scale, size.height * scale);
58 | CGImageRef cgImage =
59 | MSCDocumentCreateCGImage(_document, canvasSize, styleSheet.styleSheet);
60 | UIImage *uiImage = [UIImage imageWithCGImage:cgImage
61 | scale:[UIScreen mainScreen].scale
62 | orientation:UIImageOrientationUp];
63 | CGImageRelease(cgImage);
64 | return uiImage;
65 | }
66 |
67 | @end
68 |
--------------------------------------------------------------------------------
/Apps/StyleChecker/StyleCheckerAppDelegate.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import "StyleCheckerAppDelegate.h"
18 |
19 | #import "DirectoryContentsViewController.h"
20 | #import "StyleCheckerViewController.h"
21 |
22 | #include "MetroSVG/MetroSVG.h"
23 |
24 | @interface StyleCheckerAppDelegate ()
25 | @end
26 |
27 | @implementation StyleCheckerAppDelegate
28 |
29 | - (BOOL)application:(UIApplication *)application
30 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
31 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
32 | self.window.backgroundColor = [UIColor whiteColor];
33 | [self.window makeKeyAndVisible];
34 |
35 | NSString *resourcesPath = [[NSBundle mainBundle] resourcePath];
36 | NSString *testDataPath = [resourcesPath stringByAppendingPathComponent:@"TestData"];
37 | DirectoryContentsViewController *rootDirectoryViewController =
38 | [[DirectoryContentsViewController alloc] initWithPaths:@[ testDataPath ] title:@"ROOT"];
39 | rootDirectoryViewController.dataSource = self;
40 | UINavigationController *navigationController =
41 | [[UINavigationController alloc] initWithRootViewController:rootDirectoryViewController];
42 | self.window.rootViewController = navigationController;
43 |
44 | return YES;
45 | }
46 |
47 | #pragma mark DirectoryContentsViewControllerDataSource
48 |
49 | - (UIViewController *)
50 | directoryContentsController:(DirectoryContentsViewController *)directoryContentsController
51 | viewControllerWithFilePaths:(NSArray *)filePaths {
52 | return [[StyleCheckerViewController alloc] initWithPath:filePaths[0]
53 | cssFiles:nil];
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/MetroSVG/Public/MSCDocument.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 |
21 | #include "MetroSVG/Public/MSCStylesheet.h"
22 |
23 | #if defined __cplusplus
24 | extern "C" {
25 | #endif
26 |
27 | // MSCDocument is an opaque type that represents a single SVG document.
28 | typedef struct MSCDocument MSCDocument;
29 |
30 | // Creates an MSCDocument instance with UTF-8-encoded SVG data. The data will be
31 | // partially parsed to compute basic properties of the image. The returned
32 | // instance must be deleted with MSCDocumentDelete when it is done.
33 | // |url| can be NULL.
34 | MSCDocument *MSCDocumentCreateFromData(const char *data,
35 | size_t length,
36 | const char *url);
37 |
38 | // Deletes an MSCDocument instance.
39 | void MSCDocumentDelete(MSCDocument *document);
40 |
41 | // Fully parses data in a given MSCDocument and creates a CGImage from it.
42 | // The caller is responsible for releasing the returned object.
43 | // |style_sheet| can be NULL.
44 | CGImageRef MSCDocumentCreateCGImage(MSCDocument *document,
45 | CGSize canvas_size,
46 | const MSCStyleSheet *style_sheet);
47 |
48 | // Returns the image's intrinsic size as defined by "width" and "height"
49 | // attributes of the outermost svg element. If these attributes are not
50 | // specified, zero is assumed.
51 | CGSize MSCDocumentGetImageSize(const MSCDocument *document);
52 |
53 | // Returns value of "viewBox" attribute of the outermost svg element. Returns
54 | // CGRectNull if the attribute is not specified.
55 | CGRect MSCDocumentGetImageViewBox(const MSCDocument *document);
56 |
57 | #if defined __cplusplus
58 | } // extern "C"
59 | #endif
60 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/StringPiece.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | namespace metrosvg {
24 | namespace internal {
25 |
26 | class StringPiece {
27 | public:
28 | StringPiece()
29 | : begin_(NULL), length_(0) {}
30 |
31 | StringPiece(const char *s)
32 | : begin_(s), length_(s ? std::strlen(s) : 0) {}
33 |
34 | StringPiece(const std::string &s)
35 | : begin_(s.data()), length_(s.length()) {}
36 |
37 | StringPiece(const char *begin, size_t length)
38 | : begin_(begin), length_(length) {}
39 |
40 | StringPiece(const char *begin, const char *end)
41 | : begin_(begin), length_(end - begin) {}
42 |
43 | StringPiece(const StringPiece &rhs)
44 | : begin_(rhs.begin_), length_(rhs.length_) {}
45 |
46 | StringPiece &operator=(const StringPiece &rhs) {
47 | begin_ = rhs.begin_;
48 | length_ = rhs.length_;
49 | return *this;
50 | }
51 |
52 | bool operator==(const StringPiece &rhs) const {
53 | if (length() != rhs.length()) {
54 | return false;
55 | }
56 | for (size_t i = 0; i < length(); ++i) {
57 | if ((*this)[i] != rhs[i]) {
58 | return false;
59 | }
60 | }
61 | return true;
62 | }
63 |
64 | bool operator==(const char *rhs) const {
65 | return (*this) == StringPiece(rhs);
66 | }
67 |
68 | char operator[](size_t n) const { return *(begin_ + n); }
69 |
70 | const char *begin() const { return begin_; }
71 | const char *end() const { return begin_ + length_; }
72 | size_t length() const { return length_; }
73 |
74 | const std::string as_std_string() const;
75 |
76 | size_t find(char c) const;
77 | size_t find(const StringPiece &s) const;
78 |
79 | void Advance(size_t n);
80 |
81 | private:
82 | const char *begin_;
83 | size_t length_;
84 | };
85 |
86 | } // namespace internal
87 | } // namespace metrosvg
88 |
--------------------------------------------------------------------------------
/Apps/BatchRenderer/main.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #import "Apps/Common/SVGUtil.h"
20 |
21 | static const CGSize kCanvasSize = {640, 640};
22 |
23 | // Renders all files under |inputDir| with an extension of .svg
24 | // into the same relative path under |outputDir| as .png files.
25 | static void RenderSVGFiles(NSString *inputDir, NSString *outputDir) {
26 | NSFileManager *fileManager = [NSFileManager defaultManager];
27 | NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:inputDir];
28 | NSString *relPath;
29 |
30 | while (relPath = [enumerator nextObject]) {
31 | NSString *inputPath = [inputDir stringByAppendingPathComponent:relPath];
32 | BOOL isDirectory;
33 | [fileManager fileExistsAtPath:inputPath isDirectory:&isDirectory];
34 | if (isDirectory) {
35 | NSError *error;
36 | NSString *outputPath = [outputDir stringByAppendingPathComponent:relPath];
37 | [fileManager createDirectoryAtPath:outputPath
38 | withIntermediateDirectories:YES
39 | attributes:nil
40 | error:&error];
41 | } else if ([[relPath pathExtension] isEqualToString:@"svg"]) {
42 | NSString *relPathNoExtension = [relPath stringByDeletingPathExtension];
43 | NSString *relPathPNG = [relPathNoExtension stringByAppendingPathExtension:@"png"];
44 | NSString *outputPath = [outputDir stringByAppendingPathComponent:relPathPNG];
45 | CGImageRef image = [SVGUtil imageWithSVGFile:inputPath
46 | size:kCanvasSize];
47 | [SVGUtil writeImage:image toPNGFile:outputPath];
48 | CGImageRelease(image);
49 | }
50 | }
51 | }
52 |
53 | int main(int argc, const char * argv[]) {
54 | @autoreleasepool {
55 | NSString *inputDir = @"/tmp/SVG/TestData";
56 | NSString *outputDir = @"/tmp/SVG/Output";
57 | RenderSVGFiles(inputDir, outputDir);
58 | }
59 | return 0;
60 | }
61 |
--------------------------------------------------------------------------------
/Apps/CommandLineRenderer/main.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include
18 |
19 | #include "MetroSVG/MetroSVG.h"
20 |
21 | int main(int argc, const char *argv[]) {
22 | int status = 0;
23 | MSCDocument *document = 0;
24 | CGImageRef image = 0;
25 | CGImageDestinationRef dest = 0;
26 |
27 | do {
28 | if (argc < 3) {
29 | status = 4;
30 | fprintf(stderr, "Too few arguments.\n");
31 | break;
32 | }
33 |
34 | NSString *inputFile = [NSString stringWithCString:argv[1]
35 | encoding:NSUTF8StringEncoding];
36 | NSData *data = [NSData dataWithContentsOfFile:inputFile];
37 | if (!data) {
38 | status = 3;
39 | fprintf(stderr, "Can't read input.\n");
40 | break;
41 | }
42 |
43 | document = MSCDocumentCreateFromData([data bytes], [data length], NULL);
44 | if (!document) {
45 | status = 1;
46 | fprintf(stderr, "Error in parsing SVG.\n");
47 | break;
48 | }
49 |
50 | image = MSCDocumentCreateCGImage(document, MSCDocumentGetImageSize(document), NULL);
51 | if (!image) {
52 | status = 1;
53 | fprintf(stderr, "Error in parsing SVG.\n");
54 | break;
55 | }
56 |
57 | NSString *outputFile = [NSString stringWithCString:argv[2]
58 | encoding:NSUTF8StringEncoding];
59 | NSURL *outputURL = [NSURL fileURLWithPath:outputFile];
60 | dest = CGImageDestinationCreateWithURL((__bridge CFURLRef)outputURL,
61 | kUTTypePNG,
62 | 1,
63 | NULL);
64 | CGImageDestinationAddImage(dest, image, NULL);
65 | if (!CGImageDestinationFinalize(dest)) {
66 | status = 2;
67 | fprintf(stderr, "Can't write output.\n");
68 | break;
69 | }
70 | } while (0);
71 |
72 | if (document) MSCDocumentDelete(document);
73 | if (image) CGImageRelease(image);
74 | if (dest) CFRelease(dest);
75 |
76 | return status;
77 | }
78 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/LoggingUtils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include
24 |
25 | namespace metrosvg {
26 | namespace internal {
27 |
28 | class LogArg;
29 |
30 | std::string FormatArgs();
31 | std::string FormatArgs(const LogArg &arg1);
32 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2);
33 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
34 | const LogArg &arg3);
35 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
36 | const LogArg &arg3, const LogArg &arg4);
37 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
38 | const LogArg &arg3, const LogArg &arg4,
39 | const LogArg &arg5);
40 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
41 | const LogArg &arg3, const LogArg &arg4,
42 | const LogArg &arg5, const LogArg &arg6);
43 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
44 | const LogArg &arg3, const LogArg &arg4,
45 | const LogArg &arg5, const LogArg &arg6,
46 | const LogArg &arg7);
47 |
48 | template
49 | std::string FormatValue(T value) {
50 | std::stringstream ss;
51 | ss << value;
52 | return ss.str();
53 | }
54 |
55 | template<>
56 | std::string FormatValue(std::nullptr_t value);
57 |
58 | template<>
59 | std::string FormatValue(CGAffineTransform value);
60 |
61 | template<>
62 | std::string FormatValue(CGAffineTransform *value);
63 |
64 | template<>
65 | std::string FormatValue(CGPoint value);
66 |
67 | template<>
68 | std::string FormatValue(CGRect value);
69 |
70 | template<>
71 | std::string FormatValue(CGLineCap value);
72 |
73 | template<>
74 | std::string FormatValue(CGLineJoin value);
75 |
76 | class LogArg {
77 | public:
78 | template
79 | LogArg(const T &value)
80 | : string_value_(FormatValue(value)) {}
81 |
82 | std::string string_value() const {
83 | return string_value_;
84 | }
85 |
86 | private:
87 | std::string string_value_;
88 | };
89 |
90 | } // namespace internal
91 | } // namespace metrosvg
92 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Gradient.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/Gradient.h"
18 |
19 | #include "MetroSVG/Internal/StringPiece.h"
20 | #include "MetroSVG/Internal/TransformIterator.h"
21 | #include "MetroSVG/Internal/Utils.h"
22 |
23 | namespace metrosvg {
24 | namespace internal {
25 |
26 | Gradient::Gradient(Gradient::Type type_in, const StringMap &attributes)
27 | : type(type_in) {
28 | const std::string *id_value = FindValueOrNull(attributes, std::string("id"));
29 | if (id_value) {
30 | id = *id_value;
31 | }
32 |
33 | const std::string *gradient_transform_value =
34 | FindValueOrNull(attributes, std::string("gradientTransform"));
35 | if (gradient_transform_value) {
36 | StringPiece gradient_transform_value_sp(*gradient_transform_value);
37 | TransformIterator transform_iterator(&gradient_transform_value_sp);
38 | while (transform_iterator.Next()) {
39 | transforms.push_back(transform_iterator.transform());
40 | }
41 | }
42 |
43 | const std::string *gradient_units_value =
44 | FindValueOrNull(attributes, std::string("gradientUnits"));
45 | if (gradient_units_value != nullptr &&
46 | *gradient_units_value == "userSpaceOnUse") {
47 | units = kUnitsUserSpaceOnUse;
48 | } else {
49 | units = kUnitsObjectBoundingBox;
50 | }
51 | }
52 |
53 | CGGradientRef CreateCGGradient(const Gradient &gradient) {
54 | size_t stop_count = gradient.stops.size();
55 | std::vector components(stop_count * 4);
56 | std::vector locations(stop_count);
57 | for (size_t i = 0; i < stop_count; ++i) {
58 | GradientStop stop = gradient.stops[i];
59 | components[4 * i] = stop.color.red();
60 | components[4 * i + 1] = stop.color.green();
61 | components[4 * i + 2] = stop.color.blue();
62 | components[4 * i + 3] = stop.opacity;
63 | locations[i] = stop.offset;
64 | }
65 | CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
66 | CGGradientRef cg_gradient =
67 | CGGradientCreateWithColorComponents(color_space,
68 | components.data(),
69 | locations.data(),
70 | stop_count);
71 | CGColorSpaceRelease(color_space);
72 | return cg_gradient;
73 | }
74 |
75 | } // namespace internal
76 | } // namespace metrosvg
77 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/StyleIteratorTest.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #include "MetroSVG/Internal/StyleIterator.h"
20 |
21 | using namespace metrosvg::internal;
22 |
23 | @interface StyleIteratorTest : XCTestCase
24 | @end
25 |
26 | @implementation StyleIteratorTest
27 |
28 | - (void)test_Success_WithoutTrailingSemicolon {
29 | StyleIterator iter(new StringPiece("prop1:value1;prop2:value2"),
30 | { std::string("prop1"), std::string("prop2") });
31 | XCTAssertTrue(iter.Next());
32 | XCTAssertTrue(iter.property() == "prop1");
33 | XCTAssertTrue(iter.value() == "value1",
34 | @"%s", iter.value().as_std_string().c_str());
35 |
36 | XCTAssertTrue(iter.Next());
37 | XCTAssertTrue(iter.property() == "prop2");
38 | XCTAssertTrue(iter.value() == "value2",
39 | @"%s", iter.value().as_std_string().c_str());
40 |
41 | XCTAssertFalse(iter.Next());
42 | }
43 |
44 | - (void)test_Success_WithTrailingSemicolon {
45 | StyleIterator iter(new StringPiece("prop1:value1;prop2:value2;"),
46 | { std::string("prop1"), std::string("prop2") });
47 | XCTAssertTrue(iter.Next());
48 | XCTAssertTrue(iter.property() == "prop1");
49 | XCTAssertTrue(iter.value() == "value1", @"%s",
50 | iter.value().as_std_string().c_str());
51 |
52 | XCTAssertTrue(iter.Next());
53 | XCTAssertTrue(iter.property() == "prop2");
54 | XCTAssertTrue(iter.value() == "value2", @"%s",
55 | iter.value().as_std_string().c_str());
56 |
57 | XCTAssertFalse(iter.Next());
58 | }
59 |
60 | - (void)test_Success_Whitespace {
61 | StyleIterator iter(new StringPiece(" prop1 : value1 ; prop2 : value2 "),
62 | { std::string("prop1"), std::string("prop2") });
63 | XCTAssertTrue(iter.Next());
64 | XCTAssertTrue(iter.property() == "prop1", @"%s was not equal to %s",
65 | iter.property().as_std_string().c_str(), "prop1");
66 | XCTAssertTrue(iter.value() == "value1", @"%s was not equal to %s",
67 | iter.value().as_std_string().c_str(), "value1");
68 |
69 | XCTAssertTrue(iter.Next());
70 | XCTAssertTrue(iter.property() == "prop2");
71 | XCTAssertTrue(iter.value() == "value2", @"%s",
72 | iter.value().as_std_string().c_str());
73 |
74 | XCTAssertFalse(iter.Next());
75 | }
76 |
77 | @end
78 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/BasicTypes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include
24 |
25 | namespace metrosvg {
26 | namespace internal {
27 |
28 | typedef std::map StringMap;
29 |
30 | // RgbColor represents a color in the RGB color space.
31 | // Intensity of each color component takes a value from 0.0 to 1.0.
32 | class RgbColor {
33 | public:
34 | RgbColor()
35 | : red_(0), green_(0), blue_(0) {}
36 |
37 | RgbColor(CGFloat red, CGFloat green, CGFloat blue);
38 |
39 | CGFloat red() const { return red_; }
40 | void set_red(CGFloat red) { red_ = red; }
41 |
42 | CGFloat green() const { return green_; }
43 | void set_green(CGFloat green) { green_ = green; }
44 |
45 | CGFloat blue() const { return blue_; }
46 | void set_blue(CGFloat blue) { blue_ = blue; }
47 |
48 | private:
49 | CGFloat red_;
50 | CGFloat green_;
51 | CGFloat blue_;
52 | };
53 |
54 | struct Length {
55 | enum Unit {
56 | kUnitNone = 0,
57 |
58 | kUnitCm,
59 | kUnitEm,
60 | kUnitEx,
61 | kUnitIn,
62 | kUnitMm,
63 | kUnitPc,
64 | kUnitPercent,
65 | kUnitPt,
66 | kUnitPx,
67 | };
68 |
69 | CGFloat value;
70 | Unit unit;
71 |
72 | Length()
73 | : value(0), unit(kUnitNone) {}
74 | Length(CGFloat value_in, Unit unit_in)
75 | : value(value_in), unit(unit_in) {}
76 | };
77 |
78 | struct LineDash {
79 | std::vector dash_values;
80 | CGFloat phase;
81 |
82 | LineDash()
83 | : phase(0) {}
84 | };
85 |
86 | enum FillRule {
87 | kFillRuleNonZero,
88 | kFillRuleEvenOdd,
89 | };
90 |
91 | // Parsed value of the preserveAspectRatio attribute.
92 | struct PreserveAspectRatio {
93 | bool defer;
94 | bool no_alignment; // true if alignment value is "none".
95 |
96 | enum Alignment {
97 | kMin,
98 | kMid,
99 | kMax,
100 | };
101 | Alignment x_alignment; // must be kMid if no_alignment is true.
102 | Alignment y_alignment; // must be kMid if no_alignment is true.
103 |
104 | enum MeetOrSlice {
105 | kMeet,
106 | kSlice,
107 | };
108 | MeetOrSlice meet_or_slice;
109 |
110 | static PreserveAspectRatio default_value() {
111 | PreserveAspectRatio aspect_ratio;
112 | aspect_ratio.defer = false;
113 | aspect_ratio.no_alignment = false;
114 | aspect_ratio.x_alignment = kMid;
115 | aspect_ratio.y_alignment = kMid;
116 | aspect_ratio.meet_or_slice = kMeet;
117 | return aspect_ratio;
118 | }
119 | };
120 |
121 | } // namespace internal
122 | } // namespace metrosvg
123 |
--------------------------------------------------------------------------------
/MetroSVG.xcodeproj/xcshareddata/xcschemes/DTDVerifier.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/MetroSVG.xcodeproj/xcshareddata/xcschemes/BatchRenderer.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/MetroSVG.xcodeproj/xcshareddata/xcschemes/StyleChecker.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/MetroSVG.xcodeproj/xcshareddata/xcschemes/CommandLineRenderer.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/MetroSVG.xcodeproj/xcshareddata/xcschemes/MetroSVG-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
65 |
71 |
72 |
73 |
74 |
75 |
76 |
82 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/MetroSVG.xcodeproj/xcshareddata/xcschemes/MetroSVG-OS-X.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
65 |
71 |
72 |
73 |
74 |
75 |
76 |
82 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/PathDataIterator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 |
21 | #include "MetroSVG/Internal/StringPiece.h"
22 |
23 | namespace metrosvg {
24 | namespace internal {
25 |
26 | class StringPiece;
27 |
28 | // PathCommandType represents the path commands defined by the SVG
29 | // specification.
30 | //
31 | // NOTE: The client of PathDataIterator doesn't need distinction between
32 | // some of these commands. Maybe consolidating these values will make the
33 | // class interface cleaner and consistent.
34 | enum PathCommandType {
35 | kPathCommandTypeMoveTo = 0,
36 | kPathCommandTypeLineTo = 1,
37 | kPathCommandTypeHorizontalLineTo = 2,
38 | kPathCommandTypeVerticalLineTo = 3,
39 | kPathCommandTypeCubicBezier = 4,
40 | kPathCommandTypeShorthandCubicBezier = 5,
41 | kPathCommandTypeQuadBezier = 6,
42 | kPathCommandTypeShorthandQuadBezier = 7,
43 | kPathCommandTypeEllipticalArc = 8,
44 | kPathCommandTypeClosePath = 9,
45 | };
46 |
47 | enum PathDataFormat {
48 | kPathDataFormatPoints = 0, // polyline or polygon
49 | kPathDataFormatPath = 1, // path
50 | };
51 |
52 | class PathDataIterator {
53 | public:
54 | // format defines whether is a path with full path commands, or a points
55 | // element with simply x,y pairs.
56 | // implicit_close means that an implicit ClosePath command should be appended
57 | // to the commands found in the data.
58 | PathDataIterator(const char *data, PathDataFormat format,
59 | bool implicit_close);
60 |
61 | bool Next();
62 |
63 | PathCommandType command_type() const { return command_type_; }
64 | CGPoint point() const { return point_; }
65 | CGPoint control_point1() const { return control_point1_; }
66 | CGPoint control_point2() const { return control_point2_; }
67 | // Those four functions are for drawing arcs.
68 | CGFloat arc_radius_x() const { return arc_radius_x_; }
69 | CGFloat arc_radius_y() const { return arc_radius_y_; }
70 | bool large_arc() const { return large_arc_; }
71 | bool sweep() const { return sweep_; }
72 | CGFloat rotation() const { return rotation_; }
73 |
74 | private:
75 | StringPiece s_;
76 | bool implicit_close_, large_arc_, sweep_;
77 | PathDataFormat format_;
78 | PathCommandType command_type_;
79 | CGPoint point_, control_point1_, control_point2_;
80 | CGFloat arc_radius_x_;
81 | CGFloat arc_radius_y_;
82 | CGFloat rotation_;
83 |
84 | // For interpreting paths.
85 | bool is_first_command_;
86 | bool absolute_; // Always true for polygon/polyline.
87 | bool shown_close_path_; // Always true for polygon/polyline.
88 | CGPoint subpath_start_point_;
89 | // This has a valid value only when is_first_command_ is true.
90 | PathCommandType last_command_type_;
91 |
92 | bool ParseSingleCommandForPath();
93 | bool ParseSingleCommandForPoints();
94 |
95 | // The following routines assume the command character has already been
96 | // consumed from the StringPiece.
97 |
98 | // For ParseMoveAndLineCommand, command_type must be one of MoveTo, LineTo,
99 | // HorizontalLineTo, or VerticalLineTo.
100 | bool ParseMoveAndLineCommand(enum PathCommandType command_type);
101 | bool ParseCubicBezierCommand();
102 | bool ParseShorthandCubicBezierCommand();
103 | bool ParseQuadBezierCommand();
104 | bool ParseShorthandQuadBezierCommand();
105 | bool ParseEllipticalArcCommand();
106 | };
107 |
108 | } // namespace internal
109 | } // namespace metrosvg
110 |
--------------------------------------------------------------------------------
/AcceptanceTest/AcceptanceTest.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | #import "Apps/Common/SVGUtil.h"
21 | #include "MetroSVG/MetroSVG.h"
22 |
23 | static const CGSize kCanvasSize = {640, 640};
24 |
25 | NSString *FullFilePath(NSString *rootDir, NSString *baseName, NSString *extension) {
26 | NSString *dir = [rootDir stringByAppendingPathComponent:baseName];
27 | NSString *file = [dir stringByAppendingPathExtension:extension];
28 | return file;
29 | }
30 |
31 | @interface AcceptanceTest : XCTestCase
32 | @end
33 |
34 | @implementation AcceptanceTest {
35 | NSFileManager *_fileManager;
36 | NSString *_inputSVGDir;
37 | NSString *_actualPNGDir;
38 | NSString *_goldenPNGDir;
39 | }
40 |
41 | - (void)setUp {
42 | [super setUp];
43 | _fileManager = [NSFileManager defaultManager];
44 | NSString *resourceDir = [NSBundle bundleForClass:[self class]].resourcePath;
45 | _inputSVGDir = [resourceDir stringByAppendingPathComponent:@"TestData"];
46 | _actualPNGDir = [resourceDir stringByAppendingPathComponent:@"Actual"];
47 | _goldenPNGDir = [resourceDir stringByAppendingPathComponent:@"Golden"];
48 |
49 | // Reset the test environment.
50 | [_fileManager removeItemAtPath:_actualPNGDir error:nil];
51 | [_fileManager createDirectoryAtPath:_actualPNGDir
52 | withIntermediateDirectories:YES
53 | attributes:nil
54 | error:nil];
55 | }
56 |
57 | - (void)test {
58 | NSDirectoryEnumerator *enumerator = [_fileManager enumeratorAtPath:_goldenPNGDir];
59 | NSString *relPath;
60 | NSInteger numberOfVerifiedFiles = 0;
61 | while (relPath = [enumerator nextObject]) {
62 | NSString *goldenPNGFile = [_goldenPNGDir stringByAppendingPathComponent:relPath];
63 | BOOL isDirectory;
64 | [_fileManager fileExistsAtPath:goldenPNGFile isDirectory:&isDirectory];
65 | if (isDirectory) {
66 | [_fileManager createDirectoryAtPath:[_actualPNGDir stringByAppendingPathComponent:relPath]
67 | withIntermediateDirectories:YES
68 | attributes:nil
69 | error:nil];
70 | } else {
71 | [self verifyDataWithBaseName:[relPath stringByDeletingPathExtension]];
72 | numberOfVerifiedFiles += 1;
73 | }
74 | }
75 | XCTAssertNotEqual(numberOfVerifiedFiles, 0,
76 | @"No file was verified. There should be a bug in the project configurations or "
77 | @"the runtime environment.");
78 | }
79 |
80 | - (void)verifyDataWithBaseName:(NSString *)baseName {
81 | // First render the input svg file and save the result as png.
82 | NSString *inputSVGFile = FullFilePath(_inputSVGDir, baseName, @"svg");
83 | if (![_fileManager fileExistsAtPath:inputSVGFile]) {
84 | XCTFail(@"%@: nput SVG file doesn't exist.", baseName);
85 | return;
86 | }
87 | CGImageRef actualImage = [SVGUtil imageWithSVGFile:inputSVGFile size:kCanvasSize];
88 | NSString *actualPNGFile = FullFilePath(_actualPNGDir, baseName, @"png");
89 | [SVGUtil writeImage:actualImage toPNGFile:actualPNGFile];
90 | CGImageRelease(actualImage);
91 |
92 | // Then, compare the actual result with the golden.
93 | NSData *actualPNGData = [NSData dataWithContentsOfFile:actualPNGFile];
94 | NSString *goldenPNGFile = FullFilePath(_goldenPNGDir, baseName, @"png");
95 | NSData *goldenPNGData = [NSData dataWithContentsOfFile:goldenPNGFile];
96 | XCTAssert([actualPNGData isEqualToData:goldenPNGData],
97 | @"Detected diff between %@ and %@",
98 | actualPNGFile,
99 | goldenPNGFile);
100 | }
101 |
102 | @end
103 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 | #include
21 |
22 | #include
23 |
24 | #include "MetroSVG/Internal/BasicTypes.h"
25 | #include "MetroSVG/Internal/Constants.h"
26 | #include "MetroSVG/MetroSVG.h"
27 |
28 | namespace metrosvg {
29 | namespace internal {
30 |
31 | // This function makes it easier to use unique_ptr with a custom deleter.
32 | template
33 | std::unique_ptr MakeUniquePtr(T *t, Deleter deleter) {
34 | std::unique_ptr p(t, deleter);
35 | return p;
36 | }
37 |
38 | template
39 | const ValueType *FindValueOrNull(const std::map &map,
40 | const KeyType &key) {
41 | typename std::map::const_iterator iter = map.find(key);
42 | if (iter == map.end()) {
43 | return NULL;
44 | } else {
45 | return &(iter->second);
46 | }
47 | }
48 |
49 | // This function will look for the given key in the given map.
50 | // If it is present, it will attempt to parse the value of the
51 | // key as a floating-point number.
52 | // If the key is present and the parse is successful, it will
53 | // set the value pointed to by |out_float| and return true.
54 | // If the key is not present or if the value does not represent
55 | // a floating-point number, it will return false and the value
56 | // pointed to by |out_float| will be unchanged.
57 | bool FloatValueForKey(const StringMap &map,
58 | const std::string &key,
59 | CGFloat *out_float);
60 |
61 | bool LengthValueForKey(const StringMap &map,
62 | const std::string &key,
63 | Length *out_length);
64 |
65 | static inline CGFloat ToRadians(CGFloat degrees) {
66 | return degrees * kPi / 180.f;
67 | }
68 |
69 | static inline CGFloat ClampToUnitRange(CGFloat value) {
70 | return std::fmin(std::fmax(value, 0.f), 1.f);
71 | }
72 |
73 | // Converts representaion of an arc in start point,
74 | // end point and flags that is used by SVG to one by center,
75 | // Radius, start angle and end angle that is used by Core Graphics.
76 | // Angles are in radians.
77 | // Returns false in case of bad input.
78 | bool SvgArcToCgArc(CGPoint start_point,
79 | CGPoint end_point,
80 | bool large_arc,
81 | bool sweep,
82 | CGFloat *radius,
83 | CGPoint *center,
84 | CGFloat *start_angle,
85 | CGFloat *end_angle);
86 |
87 | // Test that angle a1 is close to angle a2.
88 | // When the difference between a1 and a2 is more than 2 * pi,
89 | // a1 is shifted to a point near a2 by multiples of 2 * pi.
90 | bool AreAnglesClose(CGFloat a1, CGFloat a2, CGFloat accuracy);
91 |
92 | // Returns an affine transform that maps a given rectangle to
93 | // a unit rectangle located at the origin ((0, 0), (1, 1)).
94 | CGAffineTransform CGAffineTransformToNormalizeRect(CGRect rect);
95 |
96 | // Returns a transform to establish a new coordinate system
97 | // as specified by |aspect_ratio| and |view_box| within the |target_viewport|
98 | // described by the current coordinate system.
99 | // NOTE: This method currently only supports view box and viewport
100 | // place at the origin.
101 | // TODO: Implement this missing feature.
102 | CGAffineTransform
103 | CGAffineTransformForPreserveAspectRatio(PreserveAspectRatio aspect_ratio,
104 | CGRect view_box,
105 | CGRect target_viewport);
106 |
107 | // Returns a unit-less length value measured in the user space evaluating
108 | // a given length value with a unit. Currently, only conversion from a
109 | // percentage, e.g., 65% -> 0.65, is supported.
110 | CGFloat EvaluateLength(Length length);
111 |
112 | } // namespace internal
113 | } // namespace metrosvg
114 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/TransformIterator.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/TransformIterator.h"
18 |
19 | #include
20 |
21 | #include "MetroSVG/Internal/BasicValueParsers.h"
22 | #include "MetroSVG/Internal/Macros.h"
23 | #include "MetroSVG/Internal/StringPiece.h"
24 | #include "MetroSVG/Internal/Utils.h"
25 |
26 | namespace metrosvg {
27 | namespace internal {
28 |
29 | TransformIterator::TransformIterator(StringPiece *s)
30 | : s_(s), is_first(true) {}
31 |
32 | bool TransformIterator::Next() {
33 | StringPiece s_copy = *s_;
34 | ConsumeWhitespace(&s_copy);
35 | if (!is_first) {
36 | ConsumeTransformDelimeters(&s_copy);
37 | }
38 | if (s_copy.length() == 0) {
39 | return false;
40 | }
41 | if (ConsumeString(&s_copy, "matrix", true)) {
42 | CGFloat elements[6];
43 | if (!ConsumeParenthesizedFloats(&s_copy, 6, elements)) {
44 | return false;
45 | }
46 | transform_ = CGAffineTransformMake(elements[0], elements[1], elements[2],
47 | elements[3], elements[4], elements[5]);
48 | } else if (ConsumeString(&s_copy, "translate", true)) {
49 | CGFloat elements[2];
50 | if (ConsumeParenthesizedFloats(&s_copy, 2, elements)) {
51 | transform_ = CGAffineTransformMakeTranslation(elements[0], elements[1]);
52 | } else if (ConsumeParenthesizedFloats(&s_copy, 1, elements)) {
53 | transform_ = CGAffineTransformMakeTranslation(elements[0], 0.);
54 | } else {
55 | return false;
56 | }
57 | } else if (ConsumeString(&s_copy, "scale", true)) {
58 | CGFloat elements[2];
59 | if (ConsumeParenthesizedFloats(&s_copy, 2, elements)) {
60 | transform_ = CGAffineTransformMakeScale(elements[0], elements[1]);
61 | } else if (ConsumeParenthesizedFloats(&s_copy, 1, elements)) {
62 | transform_ = CGAffineTransformMakeScale(elements[0], elements[0]);
63 | } else {
64 | return false;
65 | }
66 | } else if (ConsumeString(&s_copy, "rotate", true)) {
67 | CGFloat elements[3];
68 | if (ConsumeParenthesizedFloats(&s_copy, 3, elements)) {
69 | CGAffineTransform translate =
70 | CGAffineTransformMakeTranslation(elements[1], elements[2]);
71 | CGAffineTransform rotate =
72 | CGAffineTransformMakeRotation(ToRadians(elements[0]));
73 | CGAffineTransform translate_back =
74 | CGAffineTransformMakeTranslation(-elements[1], -elements[2]);
75 | transform_ =
76 | CGAffineTransformConcat(translate,
77 | CGAffineTransformConcat(rotate,
78 | translate_back));
79 | } else if (ConsumeParenthesizedFloats(&s_copy, 1, elements)) {
80 | transform_ = CGAffineTransformMakeRotation(ToRadians(elements[0]));
81 | } else {
82 | return false;
83 | }
84 | } else if (ConsumeString(&s_copy, "skewX", true)) {
85 | CGFloat skew_angle;
86 | if (!ConsumeParenthesizedFloats(&s_copy, 1, &skew_angle)) {
87 | return false;
88 | }
89 | CGFloat skew_angle_radians = ToRadians(skew_angle);
90 | transform_ = CGAffineTransformMake(1, 0, tan(skew_angle_radians), 1, 0, 0);
91 | } else if (ConsumeString(&s_copy, "skewY", true)) {
92 | CGFloat skew_angle;
93 | if (!ConsumeParenthesizedFloats(&s_copy, 1, &skew_angle)) {
94 | return false;
95 | }
96 | CGFloat skew_angle_radians = ToRadians(skew_angle);
97 | transform_ = CGAffineTransformMake(1, tan(skew_angle_radians), 0, 1, 0, 0);
98 | } else {
99 | return false;
100 | }
101 | s_->Advance(s_copy.begin() - s_->begin());
102 | is_first = false;
103 | return true;
104 | }
105 |
106 | void TransformIterator::ConsumeTransformDelimeters(StringPiece *s) const {
107 | while (true) {
108 | ConsumeWhitespace(s);
109 | if (s->length() > 0 && (*s)[0] == ',') {
110 | s->Advance(1);
111 | } else {
112 | break;
113 | }
114 | }
115 | ConsumeWhitespace(s);
116 | }
117 |
118 | } // namespace internal
119 | } // namespace metrosvg
120 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Document.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/Document.h"
18 |
19 | #include "MetroSVG/Internal/BasicValueParsers.h"
20 | #include "MetroSVG/Internal/Renderer.h"
21 | #include "MetroSVG/Internal/StringPiece.h"
22 | #include "MetroSVG/Internal/Utils.h"
23 |
24 | namespace metrosvg {
25 | namespace internal {
26 |
27 | // Get size of the outmost svg element in given svg data.
28 | bool GetImageMetaDataFromSVGData(const char *data,
29 | size_t data_length,
30 | CGSize *image_size,
31 | CGRect *view_box) {
32 | // Defaults to 100% per spec but we don't support length units yet.
33 | // http://www.w3.org/TR/SVG/struct.html#SVGElementWidthAttribute
34 | Length width(100.f, Length::kUnitNone);
35 | Length height(100.f, Length::kUnitNone);
36 |
37 | xmlTextReader *reader =
38 | xmlReaderForMemory(data, static_cast(data_length), NULL, NULL, 0);
39 | bool success = true;
40 | int last_xml_status;
41 | while ((last_xml_status = xmlTextReaderRead(reader)) > 0) {
42 | int node_type = xmlTextReaderNodeType(reader);
43 | StringPiece elem_name =
44 | reinterpret_cast(xmlTextReaderConstName(reader));
45 | if (node_type == XML_READER_TYPE_ELEMENT && elem_name == "svg") {
46 | while (xmlTextReaderMoveToNextAttribute(reader)) {
47 | StringPiece attr_name =
48 | reinterpret_cast(xmlTextReaderConstName(reader));
49 | StringPiece attr_value =
50 | reinterpret_cast(xmlTextReaderConstValue(reader));
51 | if (attr_name == "width") {
52 | if (!ParseLength(attr_value, &width)) {
53 | success = false;
54 | }
55 | } else if (attr_name == "height") {
56 | if (!ParseLength(attr_value, &height)) {
57 | success = false;
58 | }
59 | } else if (attr_name == "viewBox") {
60 | CGFloat values[4] = {0, 0, 0, 0};
61 | if (ParseFloats(attr_value, 4, values)) {
62 | *view_box =
63 | CGRectMake(values[0], values[1], values[2], values[3]);
64 | }
65 | }
66 | }
67 | break;
68 | }
69 | }
70 | xmlFreeTextReader(reader);
71 |
72 | if (last_xml_status < 0) {
73 | success = false;
74 | }
75 |
76 | if (success) {
77 | *image_size = CGSizeMake(width.value, height.value);
78 | return true;
79 | } else {
80 | return false;
81 | }
82 | }
83 |
84 | } // namespace internal
85 | } // namespace metrosvg
86 |
87 | using metrosvg::internal::GetImageMetaDataFromSVGData;
88 | using metrosvg::internal::Renderer;
89 |
90 | MSCDocument *MSCDocumentCreateFromData(const char *data,
91 | size_t length,
92 | const char *url) {
93 | CGSize size = CGSizeZero;
94 | CGRect view_box = CGRectNull;
95 | if (!GetImageMetaDataFromSVGData(data, length, &size, &view_box)) {
96 | return NULL;
97 | }
98 |
99 | MSCDocument *document = new MSCDocument;
100 | document->data = data;
101 | document->data_length = length;
102 | document->url = url;
103 | document->size = size;
104 | document->view_box = view_box;
105 | return document;
106 | }
107 |
108 | void MSCDocumentDelete(MSCDocument *document) {
109 | delete document;
110 | }
111 |
112 | CGImageRef MSCDocumentCreateCGImage(MSCDocument *document,
113 | CGSize canvas_size,
114 | const MSCStyleSheet *style_sheet) {
115 | Renderer renderer;
116 | return renderer.CreateCGImageFromMSCDocument(document,
117 | canvas_size,
118 | style_sheet);
119 | }
120 |
121 | CGSize MSCDocumentGetImageSize(const MSCDocument *document) {
122 | return document->size;
123 | }
124 |
125 | CGRect MSCDocumentGetImageViewBox(const MSCDocument *document) {
126 | return document->view_box;
127 | }
128 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/LoggingUtils.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/LoggingUtils.h"
18 |
19 | #include
20 |
21 | namespace metrosvg {
22 | namespace internal {
23 |
24 | std::string FormatArgs() {
25 | return "";
26 | }
27 |
28 | std::string FormatArgs(const LogArg &arg1) {
29 | return arg1.string_value();
30 | }
31 |
32 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2) {
33 | std::stringstream ss;
34 | ss << arg1.string_value() << ", " << arg2.string_value();
35 | return ss.str();
36 | }
37 |
38 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
39 | const LogArg &arg3) {
40 | std::stringstream ss;
41 | ss << arg1.string_value() << ", " << arg2.string_value() << ", "
42 | << arg3.string_value();
43 | return ss.str();
44 | }
45 |
46 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
47 | const LogArg &arg3, const LogArg &arg4) {
48 | std::stringstream ss;
49 | ss << arg1.string_value() << ", " << arg2.string_value() << ", "
50 | << arg3.string_value() << ", " << arg4.string_value();
51 | return ss.str();
52 | }
53 |
54 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
55 | const LogArg &arg3, const LogArg &arg4,
56 | const LogArg &arg5) {
57 | std::stringstream ss;
58 | ss << arg1.string_value() << ", " << arg2.string_value() << ", "
59 | << arg3.string_value() << ", " << arg4.string_value() << ", "
60 | << arg5.string_value();
61 | return ss.str();
62 | }
63 |
64 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
65 | const LogArg &arg3, const LogArg &arg4,
66 | const LogArg &arg5, const LogArg &arg6) {
67 | std::stringstream ss;
68 | ss << arg1.string_value() << ", " << arg2.string_value() << ", "
69 | << arg3.string_value() << ", " << arg4.string_value() << ", "
70 | << arg5.string_value() << ", " << arg6.string_value();
71 | return ss.str();
72 | }
73 |
74 | std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
75 | const LogArg &arg3, const LogArg &arg4,
76 | const LogArg &arg5, const LogArg &arg6,
77 | const LogArg &arg7) {
78 | std::stringstream ss;
79 | ss << arg1.string_value() << ", " << arg2.string_value() << ", "
80 | << arg3.string_value() << ", " << arg4.string_value() << ", "
81 | << arg5.string_value() << ", " << arg6.string_value() << ", "
82 | << arg7.string_value();
83 | return ss.str();
84 | }
85 |
86 | template<>
87 | std::string FormatValue(std::nullptr_t value) {
88 | return "NULL";
89 | }
90 |
91 | template<>
92 | std::string FormatValue(const CGAffineTransform value) {
93 | std::stringstream ss;
94 | ss << "(" << value.a << ", " << value.b << ", "
95 | << value.c << ", " << value.d << ", "
96 | << value.tx << ", " << value.ty << ")";
97 | return ss.str();
98 | }
99 |
100 | template<>
101 | std::string FormatValue(CGAffineTransform *value) {
102 | return FormatValue(*value);
103 | }
104 |
105 | template<>
106 | std::string FormatValue(const CGPoint value) {
107 | std::stringstream ss;
108 | ss << "(" << value.x << ", " << value.y << ")";
109 | return ss.str();
110 | }
111 |
112 | template<>
113 | std::string FormatValue(const CGRect value) {
114 | std::stringstream ss;
115 | ss << "(" << value.origin.x << ", " << value.origin.y << ", "
116 | << value.size.width << ", " << value.size.height << ")";
117 | return ss.str();
118 | }
119 |
120 | template<>
121 | std::string FormatValue(CGLineCap value) {
122 | switch (value) {
123 | case kCGLineCapButt:
124 | return "kCGLineCapButt";
125 | case kCGLineCapRound:
126 | return "kCGLineCapRound";
127 | case kCGLineCapSquare:
128 | return "kCGLineCapSquare";
129 | }
130 | }
131 |
132 | template<>
133 | std::string FormatValue(CGLineJoin value) {
134 | switch (value) {
135 | case kCGLineJoinMiter:
136 | return "kCGLineJoinMiter";
137 | case kCGLineJoinRound:
138 | return "kCGLineJoinRound";
139 | case kCGLineJoinBevel:
140 | return "kCGLineJoinBevel";
141 | }
142 | }
143 |
144 | } // namespace internal
145 | } // namespace metrosvg
146 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/StyleSheet.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/StyleSheet.h"
18 |
19 | #include "MetroSVG/Internal/StringPiece.h"
20 | #include "MetroSVG/Internal/StyleIterator.h"
21 |
22 | MSCStyleSheet *MSCStyleSheetCreateWithData(const char *data,
23 | size_t data_length) {
24 | return metrosvg::internal::ParseStyleSheetData(data, data_length);
25 | }
26 |
27 | void MSCStyleSheetDelete(MSCStyleSheet *style_sheet) {
28 | delete style_sheet;
29 | }
30 |
31 | namespace metrosvg {
32 | namespace internal {
33 |
34 | // ParserState is state for parsing CSS.
35 | // At OUTSIDE_CONTENTS, before reading selector name and after reading "}".
36 | // At BEFORE_VALUE, after reading selector name and before reading "{".
37 | // At FINDING_VALUE, reading values between "{" and "}".
38 | enum ParserState {
39 | OUTSIDE_CONTENTS,
40 | BEFORE_VALUE,
41 | FINDING_VALUE,
42 | };
43 |
44 | MSCStyleSheet *ParseStyleSheetData(const char *data,
45 | size_t data_length) {
46 | ParserState state = OUTSIDE_CONTENTS;
47 | std::string selector_name;
48 | std::string selector_value;
49 | std::vector> selector_data;
50 | std::unordered_set supported_styles;
51 | supported_styles.insert("fill");
52 | supported_styles.insert("stop-color");
53 | supported_styles.insert("stroke");
54 | supported_styles.insert("stroke-width");
55 | std::unique_ptr style_sheet(new MSCStyleSheet);
56 |
57 | for (size_t i = 0; i < data_length; i++) {
58 | switch (state) {
59 | case OUTSIDE_CONTENTS:
60 | switch (data[i]) {
61 | case '.':
62 | while (('a' <= data[i + 1] && data[i + 1] <= 'z') ||
63 | ('A' <= data[i + 1] && data[i + 1] <= 'Z') ||
64 | ('0' <= data[i + 1] && data[i + 1] <= '9') ||
65 | data[i + 1] == '-' || data[i + 1] == '_') {
66 | selector_name += data[(i++) + 1];
67 | }
68 | state = BEFORE_VALUE;
69 | break;
70 | case '\n':
71 | case '\t':
72 | case ' ':
73 | break;
74 | default:
75 | return NULL;
76 | }
77 | break;
78 | case BEFORE_VALUE:
79 | switch (data[i]) {
80 | case '{':
81 | state = FINDING_VALUE;
82 | break;
83 | case ' ':
84 | break;
85 | default:
86 | return NULL;
87 | }
88 | break;
89 | case FINDING_VALUE:
90 | switch (data[i]) {
91 | case '}': {
92 | StringPiece sp = StringPiece(selector_value);
93 | StyleIterator style_iter(&sp, supported_styles);
94 | while (style_iter.Next()) {
95 | const std::string style_property =
96 | style_iter.property().as_std_string();
97 | const std::string style_value =
98 | style_iter.value().as_std_string();
99 | selector_data.push_back(std::pair(style_property,
101 | style_value));
102 | }
103 | style_sheet->entry.insert(std::make_pair(selector_name,
104 | selector_data));
105 | selector_data.clear();
106 | selector_name = "";
107 | selector_value = "";
108 | state = OUTSIDE_CONTENTS;
109 | break;
110 | }
111 | case ' ':
112 | case '\n':
113 | break;
114 | default:
115 | selector_value += data[i];
116 | break;
117 | }
118 | break;
119 | }
120 | }
121 | return style_sheet.release();
122 | }
123 |
124 | void MSCStyleSheetMerge(const MSCStyleSheet &source,
125 | MSCStyleSheet *dest) {
126 | if (dest == NULL) {
127 | return;
128 | }
129 | for (auto source_item : source.entry) {
130 | auto dest_item = dest->entry.find(source_item.first);
131 | if (dest_item == dest->entry.end()) {
132 | dest->entry.insert(source_item);
133 | } else {
134 | dest_item->second.insert(dest_item->second.end(),
135 | source_item.second.begin(),
136 | source_item.second.end());
137 | }
138 | }
139 | }
140 |
141 | } // namespace internal
142 | } // namespace metrosvg
143 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/BasicValueParsers.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include
24 |
25 | #include "MetroSVG/Internal/BasicTypes.h"
26 | #include "MetroSVG/Internal/StringPiece.h"
27 | // Must include this here to get default value of SVG_COLOR_KEYWORD_SUPPORT.
28 | #include "MetroSVG/Internal/SVGStandardColor.h"
29 |
30 | namespace metrosvg {
31 | namespace internal {
32 |
33 | // There are conventions for naming functions in this file.
34 | //
35 | // A function named "Consume" takes a string pointer. It returns
36 | // whether or not a token of the given type was found at the beginning of
37 | // the string. Except where noted, it ignores any whitespace found before
38 | // the token. If the token was found, it advances the string pointer past
39 | // the token and returns the parsed value of the token via an argument.
40 | //
41 | // A function named "Parse" takes a string by value. It returns
42 | // whether or not the string consists entirely of the given token. Except
43 | // where noted, it ignores any whitespace found before the token. If the
44 | // token was found, it returns the parsed value of the token via an argument.
45 |
46 | // Consumes a minus sign "-".
47 | bool ConsumeSign(StringPiece *s);
48 |
49 | // Consumes a non-negative decimal integer value, e.g., "0", "439".
50 | bool ConsumeDecimalInt(StringPiece *s, int *n);
51 |
52 | // Consumes a non-negative decimal integer value followed by a percent
53 | // symbol, e.g., "0%", "12%", "100%", "1249%".
54 | bool ConsumeDecimalIntPercent(StringPiece *s, int *n);
55 |
56 | // Consumes a hexadecimal integer of the given width, e.g, "1fd0", "deadbeaf".
57 | // If a zero or negative width is given, parses as many hex digits as
58 | // available.
59 | bool ConsumeHexInt(StringPiece *s, int width, int *n);
60 |
61 | // Consumes or parses a float value, e.g., "0.", "13.3", "-.2", "9.41-e3".
62 | bool ConsumeFloat(StringPiece *s, CGFloat *f);
63 | bool ParseFloat(StringPiece s, CGFloat *f);
64 |
65 | // Consumes or parses the given number of floats separated by commas,
66 | // e.g., "-0.5., 65.2".
67 | bool ConsumeFloats(StringPiece *s, int count, CGFloat *farray);
68 | bool ParseFloats(StringPiece s, int count, CGFloat *farray);
69 |
70 | // Parses the given number of floats surrounded by parentheses,
71 | // e.g., "(-0.5., 65.2)".
72 | bool ConsumeParenthesizedFloats(StringPiece *s,
73 | int count,
74 | CGFloat *farray);
75 |
76 | // Consumes or parses a float value followed by a length unit,
77 | // e.g., "5.6in", "-12px".
78 | bool ConsumeLength(StringPiece *s, Length *length);
79 | bool ParseLength(StringPiece s, Length *length);
80 |
81 | // Consumes or parses a list of lengths.
82 | bool ConsumeLengths(StringPiece *s, std::vector *lengths);
83 | bool ParseLengths(StringPiece s, std::vector *lengths);
84 |
85 | // PeekAlpha returns whether the first char in the string is an English
86 | // alphabetical character. It does not ignore whitespace. If the return
87 | // value is true, it will return that character via the argument.
88 | bool PeekAlpha(StringPiece s, char *c);
89 |
90 | // ConsumeAlpha returns the same value as PeekAlpha, but also advances
91 | // the string past the character if the return value is true.
92 | bool ConsumeAlpha(StringPiece *s, char *c);
93 |
94 | // Consumes a string value. It does not ignore whitespace.
95 | bool ConsumeString(StringPiece *s, const char *string, bool case_sensitive);
96 |
97 | // Consumes a single-digit flag value used by elliptical arcs.
98 | bool ConsumeFlag(StringPiece *s, bool *flag);
99 |
100 | // Consumes or parses a color value. Values allowed for color can be found on
101 | // http://www.w3.org/TR/SVG11/types.html#DataTypeColor
102 | bool ConsumeRgbColor(StringPiece *s, RgbColor *rgb);
103 | bool ParseRgbColor(StringPiece s, RgbColor *rgb);
104 |
105 | bool ConsumeWhitespace(StringPiece *s);
106 | StringPiece TrimTrailingWhitespace(const StringPiece &s);
107 |
108 | bool ConsumeIri(StringPiece *s, StringPiece *iri);
109 | bool ParseIri(StringPiece s, StringPiece *iri);
110 |
111 | // Consumes or parses a value of the preserveAspectRatio attribute.
112 | bool ConsumePreserveAspectRatio(StringPiece *s,
113 | PreserveAspectRatio *aspect_ratio);
114 | bool ParsePreserveAspectRatio(StringPiece s,
115 | PreserveAspectRatio *aspect_ratio);
116 |
117 | bool ConsumeNumberDelimiter(StringPiece *s);
118 |
119 | } // namespace internal
120 | } // namespace metrosvg
121 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Utils.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/Utils.h"
18 |
19 | #include
20 |
21 | #include "MetroSVG/Internal/BasicValueParsers.h"
22 | #include "MetroSVG/Internal/Constants.h"
23 | #include "MetroSVG/Internal/StringPiece.h"
24 |
25 | namespace metrosvg {
26 | namespace internal {
27 |
28 | bool FloatValueForKey(const StringMap &map,
29 | const std::string &key,
30 | CGFloat *out_float) {
31 | const std::string *value = FindValueOrNull(map, key);
32 | if (value) {
33 | return ParseFloat(StringPiece(*value), out_float);
34 | }
35 | return false;
36 | }
37 |
38 | bool LengthValueForKey(const StringMap &map,
39 | const std::string &key,
40 | Length *out_length) {
41 | const std::string *value = FindValueOrNull(map, key);
42 | if (value) {
43 | return ParseLength(StringPiece(*value), out_length);
44 | }
45 | return false;
46 | }
47 |
48 | bool SvgArcToCgArc(CGPoint start_point,
49 | CGPoint end_point,
50 | bool large_arc,
51 | bool sweep,
52 | CGFloat *radius,
53 | CGPoint *center,
54 | CGFloat *start_angle,
55 | CGFloat *end_angle) {
56 | if (CGPointEqualToPoint(start_point, end_point) || *radius <= 0) {
57 | return false;
58 | }
59 | CGFloat horizontal_length =
60 | std::sqrt(std::pow(start_point.x - end_point.x, 2.f)
61 | + std::pow(start_point.y - end_point.y, 2.f));
62 | // If vertical_length has no solution,
63 | // the radius should be scaled up to the diameter.
64 | // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
65 | while (pow(*radius, 2) - pow(horizontal_length / 2, 2) < 0) {
66 | *radius = horizontal_length / 2;
67 | }
68 | CGFloat vertical_length =
69 | std::sqrt(std::pow(*radius, 2.f) - std::pow(horizontal_length / 2, 2.f));
70 | if (large_arc != sweep) vertical_length = -vertical_length;
71 | center->x = (start_point.x + end_point.x) / 2
72 | +(end_point.y - start_point.y) * vertical_length / horizontal_length;
73 | center->y = (start_point.y + end_point.y) / 2
74 | - (end_point.x - start_point.x) * vertical_length / horizontal_length;
75 | *start_angle += atan2(-center->y + start_point.y, start_point.x - center->x);
76 | *end_angle += atan2(-center->y + end_point.y, end_point.x - center->x);
77 |
78 | return true;
79 | }
80 |
81 | bool AreAnglesClose(CGFloat a1, CGFloat a2, CGFloat accuracy) {
82 | int round_count = static_cast(std::round((a2 - a1) / (2 * kPi)));
83 | a1 += 2 * kPi * round_count;
84 | return (std::fabs(a1 - a2) < accuracy);
85 | }
86 |
87 | CGAffineTransform CGAffineTransformToNormalizeRect(CGRect rect) {
88 | CGAffineTransform transform =
89 | CGAffineTransformMakeTranslation(CGRectGetMinX(rect),
90 | CGRectGetMinY(rect));
91 | transform = CGAffineTransformScale(transform, CGRectGetWidth(rect),
92 | CGRectGetHeight(rect));
93 | return transform;
94 | }
95 |
96 | namespace {
97 | CGFloat OffsetForAlignment(PreserveAspectRatio::Alignment alignment,
98 | CGFloat viewport_dimention,
99 | CGFloat object_dimention) {
100 | switch (alignment) {
101 | case PreserveAspectRatio::kMin:
102 | return 0;
103 | case PreserveAspectRatio::kMid:
104 | return (viewport_dimention - object_dimention) / 2;
105 | case PreserveAspectRatio::kMax:
106 | return viewport_dimention - object_dimention;
107 | }
108 | }
109 | } // namespace
110 |
111 | CGAffineTransform
112 | CGAffineTransformForPreserveAspectRatio(PreserveAspectRatio aspect_ratio,
113 | CGRect view_box,
114 | CGRect target_viewport) {
115 | CGFloat x_scale =
116 | CGRectGetWidth(target_viewport) / CGRectGetWidth(view_box);
117 | CGFloat y_scale =
118 | CGRectGetHeight(target_viewport) / CGRectGetHeight(view_box);
119 | if (!aspect_ratio.no_alignment) {
120 | CGFloat scale =
121 | (aspect_ratio.meet_or_slice == PreserveAspectRatio::kMeet) ?
122 | std::fmin(x_scale, y_scale) :
123 | std::fmax(x_scale, y_scale);
124 | x_scale = scale;
125 | y_scale = scale;
126 | }
127 |
128 | CGFloat scaled_width = x_scale * CGRectGetWidth(view_box);
129 | CGFloat x_offset = OffsetForAlignment(aspect_ratio.x_alignment,
130 | CGRectGetWidth(target_viewport),
131 | scaled_width);
132 | CGFloat scaled_height = y_scale * CGRectGetHeight(view_box);
133 | CGFloat y_offset = OffsetForAlignment(aspect_ratio.y_alignment,
134 | CGRectGetHeight(target_viewport),
135 | scaled_height);
136 |
137 | CGAffineTransform transform =
138 | CGAffineTransformMakeTranslation(x_offset, y_offset);
139 | transform = CGAffineTransformScale(transform, x_scale, y_scale);
140 | return transform;
141 | }
142 |
143 | CGFloat EvaluateLength(Length length) {
144 | CGFloat scale = 1.f;
145 | if (length.unit == Length::kUnitPercent) {
146 | scale = 0.01f;
147 | }
148 | return length.value * scale;
149 | }
150 |
151 | } // namespace internal
152 | } // namespace metrosvg
153 |
--------------------------------------------------------------------------------
/Apps/Common/DirectoryContentsViewController.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import "DirectoryContentsViewController.h"
18 |
19 | #pragma mark - DirectoryContent
20 |
21 | @interface DirectoryContent : NSObject
22 |
23 | @property(nonatomic, strong, readonly) NSString *name;
24 | @property(nonatomic, assign, readonly) BOOL isDirectory;
25 |
26 | - (instancetype)initWithName:(NSString *)name isDirectory:(BOOL)isDirectory;
27 |
28 | + (NSArray *)directoryContentsInDirectoryAtPath:(NSString *)path;
29 |
30 | @end
31 |
32 | @implementation DirectoryContent
33 |
34 | - (instancetype)initWithName:(NSString *)name isDirectory:(BOOL)isDirectory {
35 | self = [super init];
36 | if (self) {
37 | _name = name;
38 | _isDirectory = isDirectory;
39 | }
40 | return self;
41 | }
42 |
43 | - (BOOL)isEqual:(id)other {
44 | if (self == other) {
45 | return YES;
46 | }
47 | if (![other isKindOfClass:[self class]]) {
48 | return NO;
49 | }
50 | DirectoryContent *otherContent = (DirectoryContent *)other;
51 | return [_name isEqualToString:otherContent.name] && _isDirectory == otherContent.isDirectory;
52 | }
53 |
54 | - (NSUInteger)hash {
55 | NSUInteger hash = [_name hash];
56 | hash = hash * 13 + (_isDirectory ? 7 : 0);
57 | return hash;
58 | }
59 |
60 | + (NSArray *)directoryContentsInDirectoryAtPath:(NSString *)path {
61 | NSFileManager *fileManager = [NSFileManager defaultManager];
62 | NSArray *rawContents = [fileManager contentsOfDirectoryAtPath:path error:nil];
63 | NSMutableArray *contents = [NSMutableArray array];
64 | for (NSString *rawContent in rawContents) {
65 | if ([rawContent isEqualToString:@".DS_Store"]) {
66 | continue;
67 | }
68 | NSString *contentPath = [path stringByAppendingPathComponent:rawContent];
69 | BOOL isDirectory;
70 | if ([fileManager fileExistsAtPath:contentPath isDirectory:&isDirectory]) {
71 | DirectoryContent *content =
72 | [[DirectoryContent alloc] initWithName:rawContent isDirectory:isDirectory];
73 | [contents addObject:content];
74 | }
75 | }
76 | return [contents copy];
77 | }
78 |
79 | @end
80 |
81 | #pragma mark - DirectoryContentsViewController
82 |
83 | @implementation DirectoryContentsViewController {
84 | NSArray *_paths; // of NSString.
85 | NSArray *_commonContents; // of NSString.
86 | }
87 |
88 | - (instancetype)initWithPaths:(NSArray *)paths title:(NSString *)title {
89 | self = [super initWithStyle:UITableViewStylePlain];
90 | if (self) {
91 | self.title = title;
92 |
93 | _paths = [paths copy];
94 |
95 | NSMutableSet *commonContents;
96 | for (NSString *path in paths) {
97 | NSArray *contents = [DirectoryContent directoryContentsInDirectoryAtPath:path];
98 | if (commonContents) {
99 | [commonContents intersectSet:[NSSet setWithArray:contents]];
100 | } else {
101 | commonContents = [NSMutableSet setWithArray:contents];
102 | }
103 | }
104 | _commonContents =
105 | [[commonContents allObjects] sortedArrayUsingComparator:^(DirectoryContent *c1,
106 | DirectoryContent *c2) {
107 | return [c1.name compare:c2.name];
108 | }];
109 | }
110 | return self;
111 | }
112 |
113 | #pragma mark UITableViewDataSource
114 |
115 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
116 | return 1;
117 | }
118 |
119 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
120 | return [_commonContents count];
121 | }
122 |
123 | - (UITableViewCell *)tableView:(UITableView *)tableView
124 | cellForRowAtIndexPath:(NSIndexPath *)indexPath {
125 | static NSString *const kReuseIdentifier = @"DirectoryContentsViewController";
126 | UITableViewCell *cell =
127 | [tableView dequeueReusableCellWithIdentifier:kReuseIdentifier];
128 | if (!cell) {
129 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
130 | reuseIdentifier:kReuseIdentifier];
131 | }
132 | DirectoryContent *content = _commonContents[indexPath.row];
133 | NSString *icon = content.isDirectory ? @"\U0001F4C1" // directory icon.
134 | : @"\U0001F4C4"; // file icon.
135 | cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", icon, content.name];
136 | return cell;
137 | }
138 |
139 | #pragma mark UITableViewDelegate
140 |
141 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
142 | DirectoryContent *content = _commonContents[indexPath.row];
143 |
144 | NSMutableArray *newPaths = [NSMutableArray array];
145 | for (NSString *p in _paths) {
146 | NSString *newPath = [p stringByAppendingPathComponent:content.name];
147 | [newPaths addObject:newPath];
148 | }
149 | if (content.isDirectory) {
150 | DirectoryContentsViewController *newController =
151 | [[DirectoryContentsViewController alloc] initWithPaths:newPaths title:content.name];
152 | newController.dataSource = _dataSource;
153 | [self.navigationController pushViewController:newController animated:YES];
154 | } else {
155 | UIViewController *viewController =
156 | [_dataSource directoryContentsController:self viewControllerWithFilePaths:newPaths];
157 | if (viewController) {
158 | [self.navigationController pushViewController:viewController animated:YES];
159 | }
160 | }
161 | }
162 |
163 | @end
164 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/StyleSheetTest.mm:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #include "MetroSVG/Internal/StyleSheet.h"
20 | #include "MetroSVG/Internal/Utils.h"
21 |
22 | #define SVGAssertCSSProperty(__pair, __name, __value) \
23 | do {\
24 | XCTAssertEqual(__pair.first, __name); \
25 | XCTAssertEqual(__pair.second, __value); \
26 | } while (0)
27 |
28 | using namespace metrosvg::internal;
29 |
30 | @interface StyleSheetTest : XCTestCase
31 | @end
32 |
33 | @implementation StyleSheetTest
34 |
35 | - (void)testParseStyleSheetData_OneProperty {
36 | const char *data = ".test1 { fill: red; }";
37 | std::unique_ptr
38 | style_sheet(ParseStyleSheetData(data, strlen(data)));
39 | const std::vector> *value =
40 | FindValueOrNull(style_sheet->entry, std::string("test1"));
41 | XCTAssertTrue(value != NULL);
42 | XCTAssertEqual(value->size(), 1U);
43 | SVGAssertCSSProperty((*value)[0], "fill", "red");
44 | }
45 |
46 | - (void)testParseStyleSheetData_MultipleProperties {
47 | const char *data = ".test2{ fill:red; stroke:green; }";
48 | std::unique_ptr
49 | style_sheet(ParseStyleSheetData(data, strlen(data)));
50 | const std::vector> *value =
51 | FindValueOrNull(style_sheet->entry, std::string("test2"));
52 | XCTAssertTrue(value != NULL);
53 | XCTAssertEqual(value->size(), 2U);
54 | SVGAssertCSSProperty((*value)[0], "fill", "red");
55 | SVGAssertCSSProperty((*value)[1], "stroke", "green");
56 | }
57 |
58 | - (void)testParseStyleSheetData_MultipleSelectors {
59 | const char *data = ".test3 { fill: red; } .test4 { stroke:green; }";
60 | std::unique_ptr
61 | style_sheet(ParseStyleSheetData(data, strlen(data)));
62 | const std::vector> *value =
63 | FindValueOrNull(style_sheet->entry, std::string("test3"));
64 | XCTAssertTrue(value != NULL);
65 | XCTAssertEqual(value->size(), 1U);
66 | SVGAssertCSSProperty((*value)[0], "fill", "red");
67 | value = FindValueOrNull(style_sheet->entry, std::string("test4"));
68 | XCTAssertEqual(value->size(), 1U);
69 | SVGAssertCSSProperty((*value)[0], "stroke", "green");
70 | }
71 |
72 | - (void)testParseStyleSheetData_ErrorInvalidSelector1 {
73 | const char *data = ".te st5 { fill: red; }";
74 | std::unique_ptr
75 | style_sheet(ParseStyleSheetData(data, strlen(data)));
76 | XCTAssertTrue(style_sheet == NULL);
77 | }
78 |
79 | - (void)testParseStyleSheetData_ErrorInvalidSelector2 {
80 | const char *data = "rect .test6 { fill: red; }";
81 | std::unique_ptr
82 | style_sheet(ParseStyleSheetData(data, strlen(data)));
83 | XCTAssertTrue(style_sheet == NULL);
84 | }
85 |
86 | - (void)testSVGCSSMerge_SameSelector {
87 | const char *data_dest = ".test9 { fill:red; }";
88 | std::unique_ptr
89 | dest(ParseStyleSheetData(data_dest, strlen(data_dest)));
90 | const char *data_source = ".test9 { fill:green; }";
91 | std::unique_ptr
92 | source(ParseStyleSheetData(data_source, strlen(data_source)));
93 | MSCStyleSheetMerge(*source.get(), dest.get());
94 | const std::vector> *value =
95 | FindValueOrNull(dest->entry, std::string("test9"));
96 | XCTAssertTrue(value != NULL);
97 | XCTAssertEqual(value->size(), 2U);
98 | SVGAssertCSSProperty((*value)[0], "fill", "red");
99 | SVGAssertCSSProperty((*value)[1], "fill", "green");
100 | }
101 |
102 | - (void)testSVGCSSMerge_DifferentSelectors {
103 | const char *data_dest = ".test10 { fill:red; }";
104 | std::unique_ptr
105 | desct(ParseStyleSheetData(data_dest, strlen(data_dest)));
106 | const char *data_source = ".test11 { fill:green; }";
107 | std::unique_ptr
108 | source(ParseStyleSheetData(data_source, strlen(data_source)));
109 | MSCStyleSheetMerge(*source.get(), desct.get());
110 | const std::vector> *value =
111 | FindValueOrNull(desct->entry, std::string("test10"));
112 | XCTAssertTrue(value != NULL);
113 | XCTAssertEqual(value->size(), 1U);
114 | SVGAssertCSSProperty((*value)[0], "fill", "red");
115 | value = FindValueOrNull(desct->entry, std::string("test11"));
116 | XCTAssertEqual(value->size(), 1U);
117 | SVGAssertCSSProperty((*value)[0], "fill", "green");
118 | }
119 |
120 | - (void)testSVGCSSMerge_MultipleSourceSelectors {
121 | const char *data_dest = ".test12 { fill:red; }";
122 | std::unique_ptr
123 | dest(ParseStyleSheetData(data_dest, strlen(data_dest)));
124 | const char *data_source = ".test13 { fill: red; } .test14 { stroke:green; }";
125 | std::unique_ptr
126 | source(ParseStyleSheetData(data_source, strlen(data_source)));
127 | MSCStyleSheetMerge(*source.get(), dest.get());
128 | const std::vector> *value =
129 | FindValueOrNull(dest->entry, std::string("test12"));
130 | XCTAssertTrue(value != NULL);
131 | XCTAssertEqual(value->size(), 1U);
132 | SVGAssertCSSProperty((*value)[0], "fill", "red");
133 | value = FindValueOrNull(dest->entry, std::string("test13"));
134 | XCTAssertEqual(value->size(), 1U);
135 | SVGAssertCSSProperty((*value)[0], "fill", "red");
136 | value = FindValueOrNull(dest->entry, std::string("test14"));
137 | XCTAssertEqual(value->size(), 1U);
138 | SVGAssertCSSProperty((*value)[0], "stroke", "green");
139 | }
140 |
141 | - (void)testSVGCSSMerge_MultipleSourceProperties {
142 | const char *data_dest = ".test15 { fill:red; }";
143 | std::unique_ptr
144 | dest(ParseStyleSheetData(data_dest, strlen(data_dest)));
145 | const char *data_source = ".test15 { fill: red; stroke:green; }";
146 | std::unique_ptr
147 | source(ParseStyleSheetData(data_source, strlen(data_source)));
148 | MSCStyleSheetMerge(*source.get(), dest.get());
149 | const std::vector> *value =
150 | FindValueOrNull(dest->entry, std::string("test15"));
151 | XCTAssertTrue(value != NULL);
152 | XCTAssertEqual(value->size(), 3U);
153 | SVGAssertCSSProperty((*value)[0], "fill", "red");
154 | SVGAssertCSSProperty((*value)[1], "fill", "red");
155 | SVGAssertCSSProperty((*value)[2], "stroke", "green");
156 | }
157 |
158 | @end
159 |
--------------------------------------------------------------------------------
/Apps/StyleChecker/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/SVGStandardColor.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/SVGStandardColor.h"
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "MetroSVG/Internal/BasicValueParsers.h"
24 |
25 | namespace metrosvg {
26 | namespace internal {
27 |
28 | #if SVG_COLOR_KEYWORD_SUPPORT
29 |
30 | // The standard SVG color definitions in alphabetical order,
31 | // for fast binary searching.
32 | // This table was generated by copy/pasting from the SVG spec:
33 | // http://www.w3.org/TR/SVG/types.html#ColorKeywords
34 | // and then passing it through this Python script plus the sort
35 | // command:
36 | // import fileinput
37 | // import re
38 | // import os
39 | //
40 | // color_line_re = re.compile(
41 | // """^\s*(\w+)\s*rgb\(\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\s*\)\s*$""",
42 | // re.IGNORECASE)
43 | //
44 | // for line in fileinput.input():
45 | // line = line.strip()
46 | // m = color_line_re.match(line)
47 | // if not m:
48 | // continue
49 | // color_name = m.group(1)
50 | // red = int(m.group(2))
51 | // green = int(m.group(3))
52 | // blue = int(m.group(4))
53 | // print """ { "%s", %d, %d, %d, 255, },""" % (
54 | // color_name, red, green, blue)
55 |
56 | static const SvgStandardColorDefinition standardColorDefinitions[] = {
57 | { "aliceblue", 240, 248, 255, 255, },
58 | { "antiquewhite", 250, 235, 215, 255, },
59 | { "aqua", 0, 255, 255, 255, },
60 | { "aquamarine", 127, 255, 212, 255, },
61 | { "azure", 240, 255, 255, 255, },
62 | { "beige", 245, 245, 220, 255, },
63 | { "bisque", 255, 228, 196, 255, },
64 | { "black", 0, 0, 0, 255, },
65 | { "blanchedalmond", 255, 235, 205, 255, },
66 | { "blue", 0, 0, 255, 255, },
67 | { "blueviolet", 138, 43, 226, 255, },
68 | { "brown", 165, 42, 42, 255, },
69 | { "burlywood", 222, 184, 135, 255, },
70 | { "cadetblue", 95, 158, 160, 255, },
71 | { "chartreuse", 127, 255, 0, 255, },
72 | { "chocolate", 210, 105, 30, 255, },
73 | { "coral", 255, 127, 80, 255, },
74 | { "cornflowerblue", 100, 149, 237, 255, },
75 | { "cornsilk", 255, 248, 220, 255, },
76 | { "crimson", 220, 20, 60, 255, },
77 | { "cyan", 0, 255, 255, 255, },
78 | { "darkblue", 0, 0, 139, 255, },
79 | { "darkcyan", 0, 139, 139, 255, },
80 | { "darkgoldenrod", 184, 134, 11, 255, },
81 | { "darkgray", 169, 169, 169, 255, },
82 | { "darkgreen", 0, 100, 0, 255, },
83 | { "darkgrey", 169, 169, 169, 255, },
84 | { "darkkhaki", 189, 183, 107, 255, },
85 | { "darkmagenta", 139, 0, 139, 255, },
86 | { "darkolivegreen", 85, 107, 47, 255, },
87 | { "darkorange", 255, 140, 0, 255, },
88 | { "darkorchid", 153, 50, 204, 255, },
89 | { "darkred", 139, 0, 0, 255, },
90 | { "darksalmon", 233, 150, 122, 255, },
91 | { "darkseagreen", 143, 188, 143, 255, },
92 | { "darkslateblue", 72, 61, 139, 255, },
93 | { "darkslategray", 47, 79, 79, 255, },
94 | { "darkslategrey", 47, 79, 79, 255, },
95 | { "darkturquoise", 0, 206, 209, 255, },
96 | { "darkviolet", 148, 0, 211, 255, },
97 | { "deeppink", 255, 20, 147, 255, },
98 | { "deepskyblue", 0, 191, 255, 255, },
99 | { "dimgray", 105, 105, 105, 255, },
100 | { "dimgrey", 105, 105, 105, 255, },
101 | { "dodgerblue", 30, 144, 255, 255, },
102 | { "firebrick", 178, 34, 34, 255, },
103 | { "floralwhite", 255, 250, 240, 255, },
104 | { "forestgreen", 34, 139, 34, 255, },
105 | { "fuchsia", 255, 0, 255, 255, },
106 | { "gainsboro", 220, 220, 220, 255, },
107 | { "ghostwhite", 248, 248, 255, 255, },
108 | { "gold", 255, 215, 0, 255, },
109 | { "goldenrod", 218, 165, 32, 255, },
110 | { "gray", 128, 128, 128, 255, },
111 | { "green", 0, 128, 0, 255, },
112 | { "greenyellow", 173, 255, 47, 255, },
113 | { "grey", 128, 128, 128, 255, },
114 | { "honeydew", 240, 255, 240, 255, },
115 | { "hotpink", 255, 105, 180, 255, },
116 | { "indianred", 205, 92, 92, 255, },
117 | { "indigo", 75, 0, 130, 255, },
118 | { "ivory", 255, 255, 240, 255, },
119 | { "khaki", 240, 230, 140, 255, },
120 | { "lavender", 230, 230, 250, 255, },
121 | { "lavenderblush", 255, 240, 245, 255, },
122 | { "lawngreen", 124, 252, 0, 255, },
123 | { "lemonchiffon", 255, 250, 205, 255, },
124 | { "lightblue", 173, 216, 230, 255, },
125 | { "lightcoral", 240, 128, 128, 255, },
126 | { "lightcyan", 224, 255, 255, 255, },
127 | { "lightgoldenrodyellow", 250, 250, 210, 255, },
128 | { "lightgray", 211, 211, 211, 255, },
129 | { "lightgreen", 144, 238, 144, 255, },
130 | { "lightgrey", 211, 211, 211, 255, },
131 | { "lightpink", 255, 182, 193, 255, },
132 | { "lightsalmon", 255, 160, 122, 255, },
133 | { "lightseagreen", 32, 178, 170, 255, },
134 | { "lightskyblue", 135, 206, 250, 255, },
135 | { "lightslategray", 119, 136, 153, 255, },
136 | { "lightslategrey", 119, 136, 153, 255, },
137 | { "lightsteelblue", 176, 196, 222, 255, },
138 | { "lightyellow", 255, 255, 224, 255, },
139 | { "lime", 0, 255, 0, 255, },
140 | { "limegreen", 50, 205, 50, 255, },
141 | { "linen", 250, 240, 230, 255, },
142 | { "magenta", 255, 0, 255, 255, },
143 | { "maroon", 128, 0, 0, 255, },
144 | { "mediumaquamarine", 102, 205, 170, 255, },
145 | { "mediumblue", 0, 0, 205, 255, },
146 | { "mediumorchid", 186, 85, 211, 255, },
147 | { "mediumpurple", 147, 112, 219, 255, },
148 | { "mediumseagreen", 60, 179, 113, 255, },
149 | { "mediumslateblue", 123, 104, 238, 255, },
150 | { "mediumspringgreen", 0, 250, 154, 255, },
151 | { "mediumturquoise", 72, 209, 204, 255, },
152 | { "mediumvioletred", 199, 21, 133, 255, },
153 | { "midnightblue", 25, 25, 112, 255, },
154 | { "mintcream", 245, 255, 250, 255, },
155 | { "mistyrose", 255, 228, 225, 255, },
156 | { "moccasin", 255, 228, 181, 255, },
157 | { "navajowhite", 255, 222, 173, 255, },
158 | { "navy", 0, 0, 128, 255, },
159 | { "oldlace", 253, 245, 230, 255, },
160 | { "olive", 128, 128, 0, 255, },
161 | { "olivedrab", 107, 142, 35, 255, },
162 | { "orange", 255, 165, 0, 255, },
163 | { "orangered", 255, 69, 0, 255, },
164 | { "orchid", 218, 112, 214, 255, },
165 | { "palegoldenrod", 238, 232, 170, 255, },
166 | { "palegreen", 152, 251, 152, 255, },
167 | { "paleturquoise", 175, 238, 238, 255, },
168 | { "palevioletred", 219, 112, 147, 255, },
169 | { "papayawhip", 255, 239, 213, 255, },
170 | { "peachpuff", 255, 218, 185, 255, },
171 | { "peru", 205, 133, 63, 255, },
172 | { "pink", 255, 192, 203, 255, },
173 | { "plum", 221, 160, 221, 255, },
174 | { "powderblue", 176, 224, 230, 255, },
175 | { "purple", 128, 0, 128, 255, },
176 | { "red", 255, 0, 0, 255, },
177 | { "rosybrown", 188, 143, 143, 255, },
178 | { "royalblue", 65, 105, 225, 255, },
179 | { "saddlebrown", 139, 69, 19, 255, },
180 | { "salmon", 250, 128, 114, 255, },
181 | { "sandybrown", 244, 164, 96, 255, },
182 | { "seagreen", 46, 139, 87, 255, },
183 | { "seashell", 255, 245, 238, 255, },
184 | { "sienna", 160, 82, 45, 255, },
185 | { "silver", 192, 192, 192, 255, },
186 | { "skyblue", 135, 206, 235, 255, },
187 | { "slateblue", 106, 90, 205, 255, },
188 | { "slategray", 112, 128, 144, 255, },
189 | { "slategrey", 112, 128, 144, 255, },
190 | { "snow", 255, 250, 250, 255, },
191 | { "springgreen", 0, 255, 127, 255, },
192 | { "steelblue", 70, 130, 180, 255, },
193 | { "tan", 210, 180, 140, 255, },
194 | { "teal", 0, 128, 128, 255, },
195 | { "thistle", 216, 191, 216, 255, },
196 | { "tomato", 255, 99, 71, 255, },
197 | { "turquoise", 64, 224, 208, 255, },
198 | { "violet", 238, 130, 238, 255, },
199 | { "wheat", 245, 222, 179, 255, },
200 | { "white", 255, 255, 255, 255, },
201 | { "whitesmoke", 245, 245, 245, 255, },
202 | { "yellow", 255, 255, 0, 255, },
203 | { "yellowgreen", 154, 205, 50, 255, },
204 | };
205 |
206 | // Comparator function for an color definition and a StringPiece.
207 | // Compares the color's name to the StringPiece value.
208 | // Returns -1, 0, or 1 depending on whether the color definition
209 | // lexicographically sorts less than, equal to, or greater than
210 | // the StringPiece's value.
211 | static int CompareColorDefinitionToStringPiece(
212 | const SvgStandardColorDefinition &def,
213 | const StringPiece &sp) {
214 | const char *dp = def.name;
215 | const char *spp = sp.begin();
216 | while (spp < sp.end()) {
217 | const char dc = *dp;
218 | // First n chars are equal but color name is shorter.
219 | if (dc == 0) { return -1; }
220 | const char sc = static_cast(tolower(*spp));
221 | if (dc < sc) { return -1; }
222 | if (dc > sc) { return 1; }
223 | dp++;
224 | spp++;
225 | }
226 | // Character and lengths both equal.
227 | if (!*dp) { return 0; }
228 | // First n characters are equal but StringPiece is shorter.
229 | return 1;
230 | }
231 |
232 | // Returns the standard SVG color for the given string,
233 | // if it exists; otherwise NULL.
234 | // Implements binary search in the above static table.
235 | const SvgStandardColorDefinition *FindSVGStandardColorOrNull(
236 | const StringPiece &token) {
237 | int imin = 0;
238 | int imax = sizeof(standardColorDefinitions)
239 | / sizeof(SvgStandardColorDefinition);
240 | while (imax >= imin) {
241 | int imid = imin + (imax - imin) / 2;
242 | int comparison = CompareColorDefinitionToStringPiece(
243 | standardColorDefinitions[imid], token);
244 | if (comparison == 0) {
245 | return &standardColorDefinitions[imid];
246 | } else if (comparison < 0) {
247 | imin = imid + 1;
248 | } else {
249 | imax = imid - 1;
250 | }
251 | }
252 | // key was not found
253 | return NULL;
254 | }
255 |
256 | #endif // SVG_COLOR_KEYWORD_SUPPORT
257 |
258 | } // namespace internal
259 | } // namespace metrosvg
260 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/Renderer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include
25 |
26 | #include "MetroSVG/Internal/BasicTypes.h"
27 | #include "MetroSVG/MetroSVG.h"
28 |
29 | struct CGContext;
30 |
31 | namespace metrosvg {
32 | namespace internal {
33 |
34 | struct Gradient;
35 | class PathDataIterator;
36 | class StringPiece;
37 |
38 | class Renderer {
39 | public:
40 | Renderer();
41 | ~Renderer();
42 | CGImageRef CreateCGImageFromMSCDocument(MSCDocument *document,
43 | CGSize canvas_size,
44 | const MSCStyleSheet *style_sheet);
45 |
46 | private:
47 | typedef void (Renderer::*BeginElementHandler)(const StringMap &attributes,
48 | const StringMap &styles);
49 | typedef void (Renderer::*EndElementHandler)();
50 |
51 | // As part of the explicit GraphicsState below, we keep whether to
52 | // paint or not, and whether to paint with a gradient, for each
53 | // possible paint operation (fill and stroke).
54 | struct PaintState {
55 | bool should_paint;
56 | RgbColor color;
57 | std::string iri;
58 | CGFloat opacity;
59 |
60 | explicit PaintState(bool paint_default, const RgbColor color_default)
61 | : should_paint(paint_default),
62 | color(color_default),
63 | iri(),
64 | opacity(1.0) {}
65 |
66 | void set_should_paint(bool new_should_paint) {
67 | should_paint = new_should_paint;
68 | if (!new_should_paint) {
69 | iri.clear();
70 | }
71 | }
72 |
73 | void set_color(RgbColor new_color) {
74 | should_paint = true;
75 | color = new_color;
76 | iri.clear();
77 | }
78 |
79 | void set_iri(const std::string &new_iri) {
80 | should_paint = true;
81 | iri = new_iri;
82 | }
83 |
84 | void ApplyOpacity(CGFloat additional_opacity) {
85 | opacity *= additional_opacity;
86 | }
87 | };
88 |
89 | // Most paint state is maintained directly on the CoreGraphics
90 | // GState stack. However, we need to specifically know the value
91 | // of some items that cannot be read back out of the CGState,
92 | // so we maintain a local version of a few graphics state items.
93 | struct GraphicsState {
94 | PaintState fill;
95 | FillRule fill_rule;
96 | PaintState stroke;
97 | LineDash line_dash;
98 | // This tracks the value of the "display" attribute.
99 | bool display;
100 | // This tracks the value of the "visibility" attribute,
101 | // which inherits differently than "display". See
102 | // SVG 1.1 Section 11.5.
103 | bool visibility;
104 |
105 | // States related to gradients.
106 | RgbColor stop_color;
107 | CGFloat stop_opacity;
108 |
109 | // The default value of fill is black, but for stroke it's none.
110 | GraphicsState()
111 | : fill(true, RgbColor(0.0f, 0.0f, 0.0f)),
112 | fill_rule(kFillRuleNonZero),
113 | stroke(false, RgbColor(0.0f, 0.0f, 0.0f)),
114 | display(true),
115 | visibility(true),
116 | stop_color(0, 0, 0),
117 | stop_opacity(1) {}
118 | };
119 |
120 | struct SVGElementDefinition {
121 | const char *name;
122 | BeginElementHandler begin_handler;
123 | EndElementHandler end_handler;
124 | };
125 |
126 | struct State {
127 | SVGElementDefinition element_definition;
128 | int element_line_number;
129 | int element_column_number;
130 | GraphicsState graphics;
131 | bool defines_transparency_layer;
132 | std::string style_text_;
133 | std::string style_type_;
134 |
135 | State(SVGElementDefinition element,
136 | int line_number,
137 | int column_number,
138 | GraphicsState this_graphics)
139 | : element_definition(element),
140 | element_line_number(line_number),
141 | element_column_number(column_number),
142 | graphics(this_graphics),
143 | defines_transparency_layer(false) {}
144 | };
145 |
146 | // Internal constants.
147 | static const SVGElementDefinition kSvgElementRoot;
148 | static const SVGElementDefinition kSvgElementUnknown;
149 |
150 | // Internal variables.
151 | const std::unordered_set supported_styles_;
152 | CGContext *context_;
153 | CGSize canvas_size_;
154 | CGFloat x_scale_;
155 | CGFloat y_scale_;
156 | xmlTextReader *reader_;
157 | std::vector state_stack_;
158 | std::unique_ptr pending_gradient_;
159 | std::map gradients_;
160 | GraphicsState graphics_;
161 | std::unique_ptr style_sheet_;
162 |
163 | // TODO: Make this a constant.
164 | std::vector svg_element_definitions_;
165 |
166 | void BeginElement(const char *name,
167 | const StringMap &attributes,
168 | const StringMap &styles);
169 | void EndElement(const char *name);
170 |
171 | void ProcessCircleElement(const StringMap &attributes,
172 | const StringMap &styles);
173 | void ProcessEllipseElement(const StringMap &attributes,
174 | const StringMap &styles);
175 | void ProcessGElement(const StringMap &attributes,
176 | const StringMap &styles);
177 | void ProcessLineElement(const StringMap &attributes,
178 | const StringMap &styles);
179 |
180 | void BeginLinearGradientElement(const StringMap &attributes,
181 | const StringMap &styles);
182 | void EndLinearGradientElement();
183 |
184 | void ProcessPathElement(const StringMap &attributes,
185 | const StringMap &styles);
186 | void ProcessPolygonElement(const StringMap &attributes,
187 | const StringMap &styles);
188 | void ProcessPolylineElement(const StringMap &attributes,
189 | const StringMap &styles);
190 |
191 | void BeginRadialGradientElement(const StringMap &attributes,
192 | const StringMap &styles);
193 | void EndRadialGradientElement();
194 |
195 | void ProcessRectElement(const StringMap &attributes,
196 | const StringMap &styles);
197 | void ProcessStopElement(const StringMap &attributes,
198 | const StringMap &styles);
199 |
200 | void BeginStyleElement(const StringMap &attributes,
201 | const StringMap &styles);
202 | void EndStyleElement();
203 |
204 | void ProcessSvgElement(const StringMap &attributes,
205 | const StringMap &styles);
206 |
207 | // Attempts to process the given name and value that can be specified
208 | // as an attribute and a style.
209 | //
210 | // It returns whether the given name/value pair was a
211 | // known style (in which case it will have been processed).
212 | bool ProcessStyle(const std::string &name,
213 | const std::string &value);
214 | // This is a helper function to process the value of a fill
215 | // or stroke attribute.
216 | void ProcessFillOrStrokeValue(const std::string &value, bool is_fill);
217 |
218 | // Set the current fill or stroke color in the current context
219 | // based on the graphics state.
220 | void CallCGSetColor(bool is_fill);
221 |
222 | void ProcessDisplayValue(const std::string &value);
223 | void ProcessVisibilityValue(const std::string &value);
224 | void ProcessOpacityValue(const std::string &value);
225 | void ProcessFillRuleValue(const std::string &value);
226 | void ProcessDashArrayValue(const std::string &value);
227 | void ProcessDashOffsetValue(const std::string &value);
228 |
229 | // Returns true if all attributes and styles are processed successfully.
230 | // Returns false if there was an any error.
231 | bool ProcessCommonAttributes(StringMap *unprocessed_attributes,
232 | StringMap *unprocessed_styles);
233 |
234 | // Iterates through all the elements returned by the given
235 | // iterator and defines the result as the path in the current
236 | // graphics context.
237 | void ProcessPathData(PathDataIterator *iter);
238 |
239 | // Takes an path data iterator that points to an arc
240 | // and add the arc to a path.
241 | // If an error(Out-of-range etc) occured,
242 | // returns false without mutating the path.
243 | bool AddEllipticalArcToPath(const PathDataIterator &iter,
244 | CGMutablePathRef *path);
245 |
246 | // Called to handle a paintable element with a points= attribute
247 | // (either polygon or polyline).
248 | void PaintPolyElement(const StringMap &attributes, bool implicit_close);
249 |
250 | // This routine should be called to handle the painting of
251 | // any element based on previously set fill/stroke options.
252 | // The callback takes a context and should
253 | // set the path to be painted into the context.
254 | // The |is_fillable| parameter may be false to indicate that the
255 | // type of element being painted is not logically fillable
256 | // (line and polyline).
257 | void PaintElement(std::function define_path,
258 | bool is_fillable);
259 |
260 | // This routine is a helper which will draw the gradient referenced
261 | // by the given iri clipped by the current path.
262 | void DrawClippedGradient(const std::string &iri);
263 |
264 | // Helper functions.
265 | void InitializeCGContext();
266 | SVGElementDefinition FindElementDefinition(const char *name);
267 |
268 | // Merge css into class variable style_sheet_, create an instance
269 | // if style_sheet_ is a nullptr.
270 | void MergeStyleSheet(const MSCStyleSheet &style_sheet);
271 | };
272 |
273 | } // namespace internal
274 | } // namespace metrosvg
275 |
--------------------------------------------------------------------------------
/MetroSVG/Internal/PathDataIterator.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "MetroSVG/Internal/PathDataIterator.h"
18 |
19 | #include
20 |
21 | #include "MetroSVG/Internal/BasicValueParsers.h"
22 | #include "MetroSVG/Internal/Macros.h"
23 | #include "MetroSVG/Internal/StringPiece.h"
24 |
25 | namespace metrosvg {
26 | namespace internal {
27 |
28 | PathDataIterator::PathDataIterator(const char *data,
29 | PathDataFormat format,
30 | bool implicit_close)
31 | : s_(data),
32 | implicit_close_(implicit_close),
33 | format_(format),
34 | is_first_command_(true),
35 | absolute_(format == kPathDataFormatPoints),
36 | shown_close_path_(false),
37 | last_command_type_(kPathCommandTypeClosePath) {
38 | point_ = CGPointMake(0.0, 0.0);
39 | }
40 |
41 | bool PathDataIterator::Next() {
42 | ConsumeWhitespace(&s_);
43 | if (s_.length() == 0) {
44 | if (implicit_close_ && !shown_close_path_) {
45 | command_type_ = kPathCommandTypeClosePath;
46 | shown_close_path_ = true;
47 | return true;
48 | } else {
49 | return false;
50 | }
51 | }
52 |
53 | bool success;
54 | if (format_ == kPathDataFormatPoints) {
55 | success = ParseSingleCommandForPoints();
56 | } else {
57 | success = ParseSingleCommandForPath();
58 | }
59 | if (success) {
60 | is_first_command_ = false;
61 | last_command_type_ = command_type_;
62 | }
63 | return success;
64 | }
65 |
66 | bool PathDataIterator::ParseSingleCommandForPath() {
67 | char command_char;
68 | // See whether we're starting a new command or repeating the previous command.
69 | if (PeekAlpha(s_, &command_char)) {
70 | // Consume the char we just peeked.
71 | if (!ConsumeAlpha(&s_, &command_char)) {
72 | return false;
73 | }
74 | char normalized_command_char = command_char;
75 | absolute_ = false;
76 | if ('A' <= command_char && command_char <= 'Z') {
77 | absolute_ = true;
78 | normalized_command_char = command_char - ('A' - 'a');
79 | }
80 | switch (normalized_command_char) {
81 | case 'c':
82 | command_type_ = kPathCommandTypeCubicBezier;
83 | break;
84 | case 'h':
85 | command_type_ = kPathCommandTypeHorizontalLineTo;
86 | break;
87 | case 'l':
88 | command_type_ = kPathCommandTypeLineTo;
89 | break;
90 | case 'v':
91 | command_type_ = kPathCommandTypeVerticalLineTo;
92 | break;
93 | case 'm':
94 | command_type_ = kPathCommandTypeMoveTo;
95 | break;
96 | case 's':
97 | command_type_ = kPathCommandTypeShorthandCubicBezier;
98 | break;
99 | case 'q':
100 | command_type_ = kPathCommandTypeQuadBezier;
101 | break;
102 | case 't':
103 | command_type_ = kPathCommandTypeShorthandQuadBezier;
104 | break;
105 | case 'a':
106 | command_type_ = kPathCommandTypeEllipticalArc;
107 | break;
108 | case 'z':
109 | command_type_ = kPathCommandTypeClosePath;
110 | break;
111 | default:
112 | return false;
113 | }
114 | } else {
115 | if (is_first_command_ || (command_type_ == kPathCommandTypeClosePath)) {
116 | return false;
117 | }
118 | // All other command types can repeat their arguments, so reuse the last
119 | // command type. However, if the last type was MoveTo, it should morph into
120 | // a LineTo (see SVG 1.1 Section 8.3.2).
121 | if (command_type_ == kPathCommandTypeMoveTo) {
122 | command_type_ = kPathCommandTypeLineTo;
123 | }
124 | // Consume any comma between repeats.
125 | ConsumeNumberDelimiter(&s_);
126 | }
127 | switch (command_type_) {
128 | case kPathCommandTypeMoveTo: {
129 | bool success = ParseMoveAndLineCommand(command_type_);
130 | subpath_start_point_ = point_;
131 | return success;
132 | }
133 | case kPathCommandTypeLineTo:
134 | case kPathCommandTypeHorizontalLineTo:
135 | case kPathCommandTypeVerticalLineTo:
136 | return ParseMoveAndLineCommand(command_type_);
137 | case kPathCommandTypeCubicBezier:
138 | return ParseCubicBezierCommand();
139 | case kPathCommandTypeShorthandCubicBezier:
140 | return ParseShorthandCubicBezierCommand();
141 | case kPathCommandTypeQuadBezier:
142 | return ParseQuadBezierCommand();
143 | case kPathCommandTypeShorthandQuadBezier:
144 | return ParseShorthandQuadBezierCommand();
145 | case kPathCommandTypeEllipticalArc:
146 | return ParseEllipticalArcCommand();
147 | case kPathCommandTypeClosePath:
148 | // The default start point of the next subpath is the same as
149 | // the current subpath. SVG (see SVG 1.1 Section 8.3.3) and
150 | // Core Graphics share this behivior.
151 | point_ = subpath_start_point_;
152 | return true;
153 | }
154 | }
155 |
156 | bool PathDataIterator::ParseSingleCommandForPoints() {
157 | if (is_first_command_) {
158 | command_type_ = kPathCommandTypeMoveTo;
159 | } else {
160 | command_type_ = kPathCommandTypeLineTo;
161 | // Consume any number delimiter between points.
162 | ConsumeNumberDelimiter(&s_);
163 | }
164 | return ParseMoveAndLineCommand(command_type_);
165 | }
166 |
167 | bool PathDataIterator::ParseMoveAndLineCommand(
168 | enum PathCommandType command_type) {
169 | bool change_x = false;
170 | bool change_y = false;
171 | CGFloat values[2] = {point_.x , point_.y};
172 | switch (command_type) {
173 | case kPathCommandTypeHorizontalLineTo:
174 | if (!ConsumeFloat(&s_, values)) {
175 | return false;
176 | }
177 | change_x = true;
178 | break;
179 | case kPathCommandTypeLineTo:
180 | if (!ConsumeFloats(&s_, 2, values)) {
181 | return false;
182 | }
183 | change_x = true;
184 | change_y = true;
185 | break;
186 | case kPathCommandTypeMoveTo:
187 | if (!ConsumeFloats(&s_, 2, values)) {
188 | return false;
189 | }
190 | change_x = true;
191 | change_y = true;
192 | break;
193 | case kPathCommandTypeVerticalLineTo:
194 | if (!ConsumeFloat(&s_, values + 1)) {
195 | return false;
196 | }
197 | change_y = true;
198 | break;
199 | default:
200 | return false;
201 | }
202 | if (absolute_) {
203 | if (change_x) {
204 | point_ = CGPointMake(values[0], point_.y);
205 | }
206 | if (change_y) {
207 | point_ = CGPointMake(point_.x, values[1]);
208 | }
209 | } else {
210 | if (change_x) {
211 | point_ = CGPointMake(point_.x + values[0], point_.y);
212 | }
213 | if (change_y) {
214 | point_ = CGPointMake(point_.x, point_.y + values[1]);
215 | }
216 | }
217 | return true;
218 | }
219 |
220 | bool PathDataIterator::ParseCubicBezierCommand() {
221 | CGFloat values[6];
222 | if (!ConsumeFloats(&s_, ARRAYSIZE(values), values)) {
223 | return false;
224 | }
225 | control_point1_ = CGPointMake(values[0] + (absolute_ ? 0 : point_.x),
226 | values[1] + (absolute_ ? 0 : point_.y));
227 | control_point2_ = CGPointMake(values[2] + (absolute_ ? 0 : point_.x),
228 | values[3] + (absolute_ ? 0 : point_.y));
229 | point_ = CGPointMake(values[4] + (absolute_ ? 0 : point_.x),
230 | values[5] + (absolute_ ? 0 : point_.y));
231 | return true;
232 | }
233 |
234 | bool PathDataIterator::ParseShorthandCubicBezierCommand() {
235 | CGFloat values[4];
236 | if (!ConsumeFloats(&s_, ARRAYSIZE(values), values)) {
237 | return false;
238 | }
239 | if (last_command_type_ == kPathCommandTypeCubicBezier ||
240 | last_command_type_ == kPathCommandTypeShorthandCubicBezier) {
241 | control_point1_ = CGPointMake(point_.x + (point_.x - control_point2_.x),
242 | point_.y + (point_.y - control_point2_.y));
243 | } else {
244 | control_point1_ = point_;
245 | }
246 | control_point2_ = CGPointMake(values[0] + (absolute_ ? 0 : point_.x),
247 | values[1] + (absolute_ ? 0 : point_.y));
248 | point_ = CGPointMake(values[2] + (absolute_ ? 0 : point_.x),
249 | values[3] + (absolute_ ? 0 : point_.y));
250 | return true;
251 | }
252 |
253 | bool PathDataIterator::ParseQuadBezierCommand() {
254 | CGFloat values[4];
255 | if (!ConsumeFloats(&s_, ARRAYSIZE(values), values)) {
256 | return false;
257 | }
258 | control_point1_ = CGPointMake(values[0] + (absolute_ ? 0 : point_.x),
259 | values[1] + (absolute_ ? 0 : point_.y));
260 | point_ = CGPointMake(values[2] + (absolute_ ? 0 : point_.x),
261 | values[3] + (absolute_ ? 0 : point_.y));
262 | return true;
263 | }
264 |
265 | bool PathDataIterator::ParseShorthandQuadBezierCommand() {
266 | CGFloat values[2];
267 | if (!ConsumeFloats(&s_, ARRAYSIZE(values), values)) {
268 | return false;
269 | }
270 | if (last_command_type_ == kPathCommandTypeQuadBezier ||
271 | last_command_type_ == kPathCommandTypeShorthandQuadBezier) {
272 | control_point1_ = CGPointMake(point_.x + (point_.x - control_point1_.x),
273 | point_.y + (point_.y - control_point1_.y));
274 | } else {
275 | control_point1_ = point_;
276 | }
277 | point_ = CGPointMake(values[0] + (absolute_ ? 0 : point_.x),
278 | values[1] + (absolute_ ? 0 : point_.y));
279 | return true;
280 | }
281 |
282 | bool PathDataIterator::ParseEllipticalArcCommand() {
283 | CGFloat values[3];
284 | if (!ConsumeFloats(&s_, ARRAYSIZE(values), values)) {
285 | return false;
286 | }
287 | // Take absolute values per spec.
288 | // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
289 | arc_radius_x_ = std::fabs(values[0]);
290 | arc_radius_y_ = std::fabs(values[1]);
291 | if (arc_radius_x_ == 0 || arc_radius_y_ == 0) {
292 | return false;
293 | }
294 | rotation_ = values[2];
295 |
296 | ConsumeNumberDelimiter(&s_);
297 | if (!ConsumeFlag(&s_, &large_arc_)) {
298 | return false;
299 | }
300 |
301 | ConsumeNumberDelimiter(&s_);
302 | if (!ConsumeFlag(&s_, &sweep_)) {
303 | return false;
304 | }
305 |
306 | ConsumeNumberDelimiter(&s_);
307 | CGFloat point_coords[2];
308 | if (!ConsumeFloats(&s_, ARRAYSIZE(point_coords), point_coords)) {
309 | return false;
310 | }
311 | point_ = CGPointMake(point_coords[0] + (absolute_ ? 0 : point_.x),
312 | point_coords[1] + (absolute_ ? 0 : point_.y));
313 | return true;
314 | }
315 |
316 | } // namespace internal
317 | } // namespace metrosvg
318 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------